mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-28 00:11:54 +00:00
test(integration): enforce adoption authority boundaries
TASK-f40126ee-2485-45c8-a67b-4279e4e8704a
This commit is contained in:
1 parent
530afb3b67
commit
beb99bcbda
3 files changed
+87
No files matched your search
@@ -3170,6 +3170,14 @@ test_integrity_note:
|
|||||||
given: "An existing unfinalized private candidate ref and a separate finalized owner-bound private candidate ref"
|
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"
|
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"
|
then: "Direct intake refuses without a queue record, while the authenticated path records the exact private ref and commit in ordinary testing state"
|
||||||
|
- id: SCN-integration-adoption-approval-boundaries
|
||||||
|
given: "An ordinary source-only approval, or an adoption whose actor, action, approval revision, or provenance differs from the approved immutable binding"
|
||||||
|
when: "Preparation or a lifecycle transition is attempted"
|
||||||
|
then: "The transition refuses with its structured boundary code and no integration queue record"
|
||||||
|
- id: SCN-integration-adoption-request-replay
|
||||||
|
given: "A finalized adoption that has created its one ordinary private-ref integration request"
|
||||||
|
when: "A concurrent exact-row insert or later request replay is attempted"
|
||||||
|
then: "Real SQLite rejects the duplicate exact source row, the journal replay refuses, and exactly one queue row remains"
|
||||||
observable_outcomes:
|
observable_outcomes:
|
||||||
- "Git ref values, structured refusal codes, durable journal state, and native integration-request fields"
|
- "Git ref values, structured refusal codes, durable journal state, and native integration-request fields"
|
||||||
determinism_controls:
|
determinism_controls:
|
||||||
@@ -3180,6 +3188,8 @@ test_integrity_note:
|
|||||||
- "Mutable lifecycle bindings or overwriteable adoption journal records"
|
- "Mutable lifecycle bindings or overwriteable adoption journal records"
|
||||||
- "Claiming crash recovery without preserving actual ref effects"
|
- "Claiming crash recovery without preserving actual ref effects"
|
||||||
- "Treating a private candidate as an ordinary specialist branch"
|
- "Treating a private candidate as an ordinary specialist branch"
|
||||||
|
- "Using an unrelated, source-only, stale, or mismatched approval as adoption authority"
|
||||||
|
- "Duplicating a private-ref queue record through a concurrent row or replay"
|
||||||
relaxation:
|
relaxation:
|
||||||
did_relax_any_assertion: false
|
did_relax_any_assertion: false
|
||||||
if_true_explain_spec_basis: ""
|
if_true_explain_spec_basis: ""
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ export class IntegrationService {
|
|||||||
);
|
);
|
||||||
CREATE INDEX IF NOT EXISTS integration_state_created
|
CREATE INDEX IF NOT EXISTS integration_state_created
|
||||||
ON integration_requests(state, created_at, id);
|
ON integration_requests(state, created_at, id);
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS integration_request_exact_source
|
||||||
|
ON integration_requests(project_id, source_branch, source_commit);
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,11 @@ function lifecycleInput(context, action, adoptionId, extra = {}) {
|
|||||||
return { actorId: 'owner', adoptionId, approvalId, approvalRevision, adapter, ...extra };
|
return { actorId: 'owner', adoptionId, approvalId, approvalRevision, adapter, ...extra };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function blockedCodes(error) {
|
||||||
|
assert.equal(error.code.endsWith('_BLOCKED'), true, `expected a blocked adoption transition, got ${error.code}`);
|
||||||
|
return error.details.map((blocker) => blocker.code);
|
||||||
|
}
|
||||||
|
|
||||||
test('SCN-integration-adoption-private-ref-cas: a real temporary Git transaction atomically creates private archive and candidate refs, and stale expected refs refuse', () => {
|
test('SCN-integration-adoption-private-ref-cas: a real temporary Git transaction atomically creates private archive and candidate refs, and stale expected refs refuse', () => {
|
||||||
const context = fixture('torch-adoption-cas');
|
const context = fixture('torch-adoption-cas');
|
||||||
const adoptionId = 'fixture-adoption';
|
const adoptionId = 'fixture-adoption';
|
||||||
@@ -210,3 +215,73 @@ test('SCN-integration-adoption-private-ref-intake: finalized private refs enter
|
|||||||
assert.equal(requested.integrationRequest.targetBranch, 'main');
|
assert.equal(requested.integrationRequest.targetBranch, 'main');
|
||||||
context.control.close();
|
context.control.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('SCN-integration-adoption-approval-boundaries: unrelated or source-only approval records cannot authorize an owner adoption, and actor, action, revision, and provenance mismatches each refuse', () => {
|
||||||
|
const unrelated = fixture('torch-adoption-unrelated-approval');
|
||||||
|
const unrelatedId = 'fixture-adoption';
|
||||||
|
const unrelatedApproval = unrelated.control.requestApproval({
|
||||||
|
requester: unrelated.contributor, approver: 'owner', task: 'TASK-unrelated',
|
||||||
|
title: 'Ordinary source branch review', summary: 'Not an integration-adoption authority.',
|
||||||
|
});
|
||||||
|
const unrelatedApproved = unrelated.control.decideApproval({
|
||||||
|
approvalId: unrelatedApproval.id, decidedBy: 'owner', decision: 'approved', expectedRevision: unrelatedApproval.revision,
|
||||||
|
note: JSON.stringify({ schema: 'torch.dev/ordinary-source-review/v1alpha1', sourceArea: unrelated.contributor }),
|
||||||
|
});
|
||||||
|
const unrelatedInput = {
|
||||||
|
actorId: 'owner', adoptionId: unrelatedId, candidateSha: unrelated.candidate, baseTargetSha: unrelated.base,
|
||||||
|
contributorArea: unrelated.contributor, destinationArea: unrelated.destination, targetBranch: 'main',
|
||||||
|
candidateRef: `refs/torch/integration-candidates/${unrelatedId}`, expectedOldRef: 'refs/heads/main',
|
||||||
|
approvalId: unrelatedApproved.id, approvalRevision: unrelatedApproved.revision,
|
||||||
|
provenance: ['fixture:owner-approved', `candidate:${unrelated.candidate}`],
|
||||||
|
provenanceManifestDigest: digest(['fixture:owner-approved', `candidate:${unrelated.candidate}`]),
|
||||||
|
adapter: { name: unrelated.service.adoption.refAdapter.name, id: unrelated.service.adoption.refAdapter.id },
|
||||||
|
};
|
||||||
|
assert.throws(() => unrelated.service.prepareAdoption(unrelatedInput), (error) => blockedCodes(error).includes('ADOPTION_APPROVAL_BINDING_INVALID'));
|
||||||
|
assert.deepEqual(unrelated.service.list(), []);
|
||||||
|
unrelated.control.close();
|
||||||
|
|
||||||
|
const wrongActor = fixture('torch-adoption-wrong-actor');
|
||||||
|
assert.throws(() => wrongActor.service.prepareAdoption({
|
||||||
|
...input(wrongActor, 'prepare', 'fixture-adoption'), actorId: wrongActor.contributor,
|
||||||
|
}), (error) => blockedCodes(error).includes('OWNER_ACTOR_REQUIRED'));
|
||||||
|
wrongActor.control.close();
|
||||||
|
|
||||||
|
const wrongAction = fixture('torch-adoption-wrong-action');
|
||||||
|
prepare(wrongAction, 'fixture-adoption');
|
||||||
|
assert.throws(() => wrongAction.service.finalizeAdoption(lifecycleInput(wrongAction, 'rollback', 'fixture-adoption')),
|
||||||
|
(error) => blockedCodes(error).includes('ADOPTION_APPROVAL_BINDING_INVALID'));
|
||||||
|
wrongAction.control.close();
|
||||||
|
|
||||||
|
const staleRevision = fixture('torch-adoption-stale-revision');
|
||||||
|
prepare(staleRevision, 'fixture-adoption');
|
||||||
|
const staleInput = lifecycleInput(staleRevision, 'finalize', 'fixture-adoption');
|
||||||
|
assert.throws(() => staleRevision.service.finalizeAdoption({ ...staleInput, approvalRevision: staleInput.approvalRevision - 1 }),
|
||||||
|
(error) => blockedCodes(error).includes('ADOPTION_APPROVAL_REVISION_STALE'));
|
||||||
|
staleRevision.control.close();
|
||||||
|
|
||||||
|
const wrongProvenance = fixture('torch-adoption-wrong-provenance');
|
||||||
|
assert.throws(() => wrongProvenance.service.prepareAdoption({
|
||||||
|
...input(wrongProvenance, 'prepare', 'fixture-adoption'), provenance: ['fixture:owner-approved', 'unapproved:alternate-provenance'],
|
||||||
|
}), (error) => blockedCodes(error).includes('ADOPTION_PROVENANCE_DIGEST_MISMATCH'));
|
||||||
|
wrongProvenance.control.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('SCN-integration-adoption-request-replay: real SQLite rejects a duplicate exact private-ref queue row, and a completed adoption request cannot replay into a second row', () => {
|
||||||
|
const context = fixture('torch-adoption-request-replay');
|
||||||
|
const adoptionId = 'fixture-adoption';
|
||||||
|
prepare(context, adoptionId);
|
||||||
|
const finalized = context.service.finalizeAdoption(lifecycleInput(context, 'finalize', adoptionId));
|
||||||
|
const requested = context.service.requestAdoptedCandidate(lifecycleInput(context, 'request', adoptionId));
|
||||||
|
const duplicate = context.control.database.prepare(`INSERT INTO integration_requests (
|
||||||
|
id, project_id, source_area, source_branch, source_commit, target_branch,
|
||||||
|
base_target_commit, state, reason, required_checks, created_at, updated_at
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
||||||
|
assert.throws(() => duplicate.run(
|
||||||
|
'duplicate-race-row', context.control.projectId, context.contributor, finalized.candidateRef, context.candidate,
|
||||||
|
'main', context.base, 'testing', null, '[]', requested.requestedAt, requested.requestedAt,
|
||||||
|
), /UNIQUE constraint failed: integration_requests.project_id, integration_requests.source_branch, integration_requests.source_commit/);
|
||||||
|
assert.throws(() => context.service.requestAdoptedCandidate(lifecycleInput(context, 'request', adoptionId)),
|
||||||
|
(error) => error.code === 'ADOPTION_REQUEST_STATE_INVALID');
|
||||||
|
assert.deepEqual(context.service.list().map((record) => record.id), [requested.integrationRequest.id]);
|
||||||
|
context.control.close();
|
||||||
|
});
|
||||||
Reference in new issue
Block a user