Harden AGE self-infrastructure lifecycle
This commit is contained in:
parent
288847fcbf
commit
f1bd2f031e
3 changed files with 167 additions and 3 deletions
|
|
@ -107,6 +107,9 @@ function validateAgeSelfCheckpointEvidence({
|
|||
checkpointEvidence?.development_id !== lane.development_id ||
|
||||
checkpointEvidence?.task_event_id !== lane.task_event?.task_event_id ||
|
||||
checkpointEvidence?.scope_amendment_id !== authorizationAmendmentId ||
|
||||
!/^GUARD-[a-f0-9]{16}$/u.test(checkpointEvidence?.source_alert_id ?? "") ||
|
||||
!Number.isInteger(checkpointEvidence?.source_window_number) ||
|
||||
checkpointEvidence.source_window_number < 1 ||
|
||||
!checkpointEvidence?.path ||
|
||||
!isSha256(checkpointEvidence?.sha256) ||
|
||||
JSON.stringify(sections) !==
|
||||
|
|
@ -164,31 +167,67 @@ export function classifyAgeSelfInfrastructureLane({
|
|||
) {
|
||||
fail("AGE_SELF_CLASSIFICATION_IDENTITY_OR_OBJECT_SCOPE_INVALID");
|
||||
}
|
||||
if (laneKind(lane) !== LANE_KIND_UNCLASSIFIED) {
|
||||
fail("AGE_SELF_CLASSIFICATION_REQUIRES_UNCLASSIFIED_EMPTY_LANE");
|
||||
const currentLaneKind = laneKind(lane);
|
||||
if (
|
||||
currentLaneKind !== LANE_KIND_UNCLASSIFIED &&
|
||||
currentLaneKind !== LANE_KIND_AGE_SELF_INFRASTRUCTURE
|
||||
) {
|
||||
fail("AGE_SELF_CLASSIFICATION_CANNOT_REPLACE_EXTERNAL_OBJECT_LANE");
|
||||
}
|
||||
validateAgeSelfCheckpointEvidence({
|
||||
lane,
|
||||
checkpointEvidence,
|
||||
authorizationAmendmentId,
|
||||
});
|
||||
const existing = [...(lane.lane_kind_history ?? [])].reverse().find(
|
||||
(entry) => entry.next_lane_kind === LANE_KIND_AGE_SELF_INFRASTRUCTURE,
|
||||
);
|
||||
if (currentLaneKind === LANE_KIND_AGE_SELF_INFRASTRUCTURE && existing) {
|
||||
const sameEvidence =
|
||||
existing.task_event_id === lane.task_event.task_event_id &&
|
||||
existing.checkpoint_path === checkpointEvidence.path &&
|
||||
existing.checkpoint_sha256 === checkpointEvidence.sha256 &&
|
||||
existing.authorization_amendment_id === authorizationAmendmentId;
|
||||
if (sameEvidence) return lane;
|
||||
if (
|
||||
existing.task_event_id === lane.task_event.task_event_id &&
|
||||
(existing.source_alert_id === checkpointEvidence.source_alert_id ||
|
||||
!Number.isInteger(existing.source_window_number) ||
|
||||
checkpointEvidence.source_window_number <= existing.source_window_number)
|
||||
) {
|
||||
fail("AGE_SELF_CLASSIFICATION_ALREADY_EXISTS_WITH_DIFFERENT_EVIDENCE");
|
||||
}
|
||||
}
|
||||
const classification = {
|
||||
previous_lane_kind: LANE_KIND_UNCLASSIFIED,
|
||||
previous_lane_kind: currentLaneKind,
|
||||
next_lane_kind: LANE_KIND_AGE_SELF_INFRASTRUCTURE,
|
||||
task_event_id: lane.task_event.task_event_id,
|
||||
task_fingerprint: lane.task_lock.fingerprint,
|
||||
checkpoint_path: checkpointEvidence.path,
|
||||
checkpoint_sha256: checkpointEvidence.sha256,
|
||||
source_alert_id: checkpointEvidence.source_alert_id,
|
||||
source_window_number: checkpointEvidence.source_window_number,
|
||||
authorization_amendment_id: authorizationAmendmentId,
|
||||
classified_at: classifiedAt,
|
||||
classification_basis:
|
||||
"CURRENT_PERSONA_AUTHORED_CHECKPOINT_AND_EXPLICIT_HUMAN_SCOPE_AMENDMENT",
|
||||
authority_effect: "NO_EXTERNAL_AUTHORITY_GRANTED",
|
||||
};
|
||||
const bindingHistory = [...(lane.persona_source_binding_history ?? [])];
|
||||
if (lane.persona_source_binding) {
|
||||
bindingHistory.push({
|
||||
...lane.persona_source_binding,
|
||||
state: "STALE_SUPERSEDED_BY_NEW_PERSONA_CHECKPOINT",
|
||||
invalidated_at: classifiedAt,
|
||||
invalidated_by_checkpoint_sha256: checkpointEvidence.sha256,
|
||||
});
|
||||
}
|
||||
return {
|
||||
...lane,
|
||||
lane_kind: LANE_KIND_AGE_SELF_INFRASTRUCTURE,
|
||||
lane_kind_history: [...(lane.lane_kind_history ?? []), classification],
|
||||
persona_source_binding: null,
|
||||
persona_source_binding_history: bindingHistory,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue