mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-28 00:11:54 +00:00
fix(integration): bind private intake to adoption
TASK-f40126ee-2485-45c8-a67b-4279e4e8704a
This commit is contained in:
1 parent
63dd032b7f
commit
530afb3b67
4 files changed
+32
-5
No files matched your search
@@ -3167,9 +3167,9 @@ test_integrity_note:
|
||||
when: "Rollback is requested"
|
||||
then: "The completed rollback is recovered once and divergent candidate bytes refuse"
|
||||
- id: SCN-integration-adoption-private-ref-intake
|
||||
given: "A finalized owner-bound private candidate ref"
|
||||
when: "Native qualification is requested"
|
||||
then: "The normal integration queue records the exact private ref and commit in ordinary testing state"
|
||||
given: "An existing unfinalized private candidate ref and a separate finalized owner-bound private candidate ref"
|
||||
when: "Direct private-ref intake and authenticated native qualification are requested"
|
||||
then: "Direct intake refuses without a queue record, while the authenticated path records the exact private ref and commit in ordinary testing state"
|
||||
observable_outcomes:
|
||||
- "Git ref values, structured refusal codes, durable journal state, and native integration-request fields"
|
||||
determinism_controls:
|
||||
|
||||
@@ -335,7 +335,8 @@ export class AdoptionService {
|
||||
requestApprovalId: text(input.approvalId, 'approvalId'), requestApprovalRevision: input.approvalRevision, requestStartedAt: this.clock().toISOString() };
|
||||
if (record.state !== 'requesting') this.#append(record.id, record.revision, requesting, 'integration.adoption.request-started');
|
||||
const request = findIntegrationRequest?.({ candidateRef: requesting.candidateRef, commit: requesting.candidateSha })
|
||||
?? requestIntegration({ areaId: requesting.contributorArea, commit: requesting.candidateSha, candidateRef: requesting.candidateRef });
|
||||
?? requestIntegration({ adoptionId: requesting.id, areaId: requesting.contributorArea,
|
||||
commit: requesting.candidateSha, candidateRef: requesting.candidateRef });
|
||||
const requested = { ...requesting, revision: requesting.revision + 1, state: 'requested', integrationRequestId: request.id, requestedAt: this.clock().toISOString() };
|
||||
this.#append(requesting.id, requesting.revision, requested, 'integration.adoption.request');
|
||||
return { ...requested, integrationRequest: request, mutationPerformed: true };
|
||||
|
||||
@@ -106,12 +106,25 @@ export class IntegrationService {
|
||||
}
|
||||
|
||||
requestCandidate({ areaId, commit, candidateRef } = {}) {
|
||||
throw new TorchError('Private candidate intake requires an authenticated finalized adoption', {
|
||||
code: 'INTEGRATION_ADOPTED_INTAKE_INTERNAL_ONLY', details: { areaId, commit, candidateRef },
|
||||
});
|
||||
}
|
||||
|
||||
#requestFinalizedCandidate({ adoptionId, areaId, commit, candidateRef } = {}) {
|
||||
const area = this.controlPlane.assertIdentity(areaId);
|
||||
if (area === 'session-manager') {
|
||||
throw new TorchError('Session Manager does not own a feature worktree by default', {
|
||||
code: 'INTEGRATION_SOURCE_INVALID',
|
||||
});
|
||||
}
|
||||
const adoption = this.adoption.getPrepared(text(adoptionId, 'adoptionId'));
|
||||
if (adoption.state !== 'requesting' || adoption.contributorArea !== area
|
||||
|| adoption.candidateSha !== commit || adoption.candidateRef !== candidateRef) {
|
||||
throw new TorchError('Private candidate does not match an authenticated finalized adoption', {
|
||||
code: 'INTEGRATION_ADOPTED_BINDING_INVALID', details: { adoptionId, state: adoption.state },
|
||||
});
|
||||
}
|
||||
const ref = text(candidateRef, 'candidateRef');
|
||||
if (!/^refs\/torch\/integration-candidates\/[A-Za-z0-9._-]+$/.test(ref)) {
|
||||
throw new TorchError('Adopted candidates must use a private integration candidate ref', {
|
||||
@@ -185,7 +198,7 @@ export class IntegrationService {
|
||||
|
||||
requestAdoptedCandidate(input = {}) {
|
||||
return this.adoption.requestAdoptedCandidate(input, {
|
||||
requestIntegration: ({ areaId, commit, candidateRef }) => this.requestCandidate({ areaId, commit, candidateRef }),
|
||||
requestIntegration: ({ adoptionId, areaId, commit, candidateRef }) => this.#requestFinalizedCandidate({ adoptionId, areaId, commit, candidateRef }),
|
||||
findIntegrationRequest: ({ candidateRef, commit }) => this.findCandidateRequest({ candidateRef, commit }),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -185,6 +185,19 @@ test('SCN-integration-adoption-rollback-recovery: a journal-missing rollback com
|
||||
});
|
||||
|
||||
test('SCN-integration-adoption-private-ref-intake: finalized private refs enter the ordinary native integration queue, not a specialist branch shortcut', () => {
|
||||
const unfinalized = fixture('torch-adoption-unfinalized-intake');
|
||||
const unfinalizedId = 'fixture-adoption';
|
||||
const unfinalizedRef = `refs/torch/integration-candidates/${unfinalizedId}`;
|
||||
unfinalized.service.adoption.refAdapter.compareAndSwapRefs({
|
||||
expected: [{ ref: unfinalizedRef, sha: null }],
|
||||
writes: [{ ref: unfinalizedRef, sha: unfinalized.candidate }],
|
||||
});
|
||||
assert.throws(() => unfinalized.service.requestCandidate({
|
||||
areaId: unfinalized.contributor, commit: unfinalized.candidate, candidateRef: unfinalizedRef,
|
||||
}), (error) => error.code === 'INTEGRATION_ADOPTED_INTAKE_INTERNAL_ONLY');
|
||||
assert.deepEqual(unfinalized.service.list(), []);
|
||||
unfinalized.control.close();
|
||||
|
||||
const context = fixture('torch-adoption-native-intake');
|
||||
const adoptionId = 'fixture-adoption';
|
||||
prepare(context, adoptionId);
|
||||
|
||||
Reference in new issue
Block a user