fix(integration): bind private intake to adoption

TASK-f40126ee-2485-45c8-a67b-4279e4e8704a
This commit is contained in:
thePR0M3TH3AN committed 2026-10-03 17:34:09 -04:00
1 parent 63dd032b7f
commit 530afb3b67
4 files changed
+32 -5

No files matched your search

+3 -3
View File
@@ -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:
+2 -1
View File
@@ -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 };
+14 -1
View File
@@ -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 }),
});
}
+13
View File
@@ -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);