-
Notifications
You must be signed in to change notification settings - Fork 10
feat(storage): centralize system-record runtime authority #2140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7a8bfa8
5015aca
0ba3bb6
10925a7
fb69e64
0cfb1ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,7 @@ import { | |
| import { | ||
| assertAuthenticSystemRecordAppliedSnapshotV1, | ||
| assertSystemRecordRootClaimSnapshotV1, | ||
| requiresSystemRecordSnapshotRematerializationV1, | ||
| type SystemRecordAppliedSnapshotV1, | ||
| } from './system-record-state-snapshot-v1-internal.js'; | ||
| import { | ||
|
|
@@ -231,7 +232,8 @@ export function deriveSystemRecordActiveReplacementV1(input: { | |
| ? snapshot.ownedSubjectTable | ||
| : Object.freeze([]) as OwnedSubjectTableObjectV1; | ||
|
|
||
| if (authority.equalHead) { | ||
| if (authority.equalHead && !(snapshot.state === 'present' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Model rematerialization before the equal-head branch instead of negating it at the call site What's wrong Example Suggested direction For Agents There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Fold rematerialization into the authority classification instead of special-casing equal heads What's wrong Example Suggested direction For Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validated as a maintainability refinement, not a correctness blocker for this default-off runtime foundation. Deferred explicitly to #2155, which now requires the authority decision to expose a direct reusable/rematerialize outcome before activation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Make equal-head rematerialization an explicit state, not a hidden exception What's wrong Example Suggested direction For Agents |
||
| && requiresSystemRecordSnapshotRematerializationV1(snapshot))) { | ||
| if (snapshot.state !== 'present') { | ||
| throw new Error('equal system-record head cannot exist in absent state'); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { | ||
| SYSTEM_RECORD_MAX_RUNTIME_ACCOUNTED_BYTES, | ||
| } from '@origintrail-official/dkg-core/system-record-v1'; | ||
|
|
||
| export interface SystemRecordRuntimeReservationGateV1 { | ||
| acquire(owner: object, bytes: number): void; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Make the reservation gate own the lease token instead of accepting release metadata What's wrong Example Suggested direction For Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validated as a worthwhile API hardening refactor, not a behavioral blocker for the default-off foundation. Deferred explicitly to #2155, which now requires an opaque gate-owned reservation token while preserving exact-once release and process-wide exclusion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Issue: Return an opaque reservation token instead of exposing owner/byte bookkeeping What's wrong Example Suggested direction For Agents |
||
| release(owner: object, bytes: number): void; | ||
| } | ||
|
|
||
| /** One exact, nonqueued reservation with no partial-release state. */ | ||
| export function createSystemRecordNonQueuedReservationGateV1(): SystemRecordRuntimeReservationGateV1 { | ||
| let liveOwner: object | null = null; | ||
| let accountedBytes = 0; | ||
| return Object.freeze({ | ||
| acquire(owner: object, bytes: number): void { | ||
| if (!Number.isSafeInteger(bytes) || bytes <= 0 | ||
| || liveOwner !== null | ||
| || accountedBytes + bytes > SYSTEM_RECORD_MAX_RUNTIME_ACCOUNTED_BYTES) { | ||
| throw new Error('system-record atomic transient reservation is already live'); | ||
| } | ||
| liveOwner = owner; | ||
| accountedBytes += bytes; | ||
| }, | ||
| release(owner: object, bytes: number): void { | ||
| if (liveOwner !== owner || accountedBytes !== bytes) { | ||
| throw new Error('system-record atomic transient accountant state is inconsistent'); | ||
| } | ||
| liveOwner = null; | ||
| accountedBytes = 0; | ||
| }, | ||
| }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| import { | ||
| isManagedOxigraphOwnershipLeaseV1, | ||
| readManagedOxigraphOwnershipSnapshotV1, | ||
| type ManagedOxigraphOwnershipLeaseV1, | ||
| } from './managed-oxigraph-ownership-v1-internal.js'; | ||
| import { | ||
| createSystemRecordVerifiedReplacementRegistryForRuntimeV1, | ||
| type SystemRecordVerifiedReplacementRegistryV1, | ||
| } from './system-record-verified-replacement-v1-internal.js'; | ||
| import { createSystemRecordNonQueuedReservationGateV1 } from './system-record-reservation-gate-v1-internal.js'; | ||
|
|
||
| /** One nonqueued process-wide gate shared by every authentic managed endpoint. */ | ||
| const PROCESS_RESERVATION_GATE = createSystemRecordNonQueuedReservationGateV1(); | ||
|
|
||
| const OWNED_RUNTIMES = new WeakMap< | ||
| ManagedOxigraphOwnershipLeaseV1, | ||
| SystemRecordVerifiedReplacementRegistryV1 | ||
| >(); | ||
|
|
||
| /** | ||
| * Resolve the single proof runtime bound to an authentic daemon ownership lease. | ||
| * Persisted options and structural look-alikes cannot mint this authority. | ||
| */ | ||
| export function resolveOwnedSystemRecordRuntimeV1( | ||
| lease: ManagedOxigraphOwnershipLeaseV1, | ||
| ): SystemRecordVerifiedReplacementRegistryV1 { | ||
| if (!isManagedOxigraphOwnershipLeaseV1(lease)) { | ||
| throw new Error('system-record runtime requires an authentic managed Oxigraph ownership lease'); | ||
| } | ||
| const ownership = readManagedOxigraphOwnershipSnapshotV1(lease); | ||
| if (ownership?.queryEndpoint === undefined || ownership.updateEndpoint === undefined) { | ||
| throw new Error('system-record runtime requires an endpoint-bound managed Oxigraph ownership lease'); | ||
| } | ||
| const existing = OWNED_RUNTIMES.get(lease); | ||
| if (existing !== undefined) return existing; | ||
|
|
||
| const runtime = createSystemRecordVerifiedReplacementRegistryForRuntimeV1({ | ||
| reservationGate: PROCESS_RESERVATION_GATE, | ||
| assertAvailable: () => { | ||
| const snapshot = readManagedOxigraphOwnershipSnapshotV1(lease); | ||
| if (!snapshot?.ready || snapshot.terminal | ||
| || snapshot.queryEndpoint !== ownership.queryEndpoint | ||
| || snapshot.updateEndpoint !== ownership.updateEndpoint) { | ||
| throw new Error('system-record runtime ownership lease is not ready'); | ||
| } | ||
| }, | ||
| }); | ||
| OWNED_RUNTIMES.set(lease, runtime); | ||
| return runtime; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Issue: Adapter wiring is not verified with a lease-issued proof
What's wrong
The PR's key storage-boundary behavior is that the adapter receives the same lease-owned runtime consumer that the verifier issuer will use. Current tests exercise the runtime directly and only check that the adapter rejects a forged object, which would also pass if the adapter were wired to the wrong private registry. That leaves the changed integration contract unverified.
Example
A regression that accidentally changed the adapter back to a fresh private registry would still reject
Object.freeze({})and the direct runtime tests would still pass, but a handle issued byresolveOwnedSystemRecordRuntimeV1(ownership.lease).issuerwould fail throughsession.applyVerified(handle)instead of being consumed by the adapter's atomic executor.Suggested direction
Cover the production composition, not only the resolver in isolation: the test should prove the store consumes handles from the same lease-bound runtime it resolves here.
Confidence note
I found direct tests for the lease runtime and for the atomic executor, plus an adapter test that only sends a forged object. I did not find an adapter test that sends a valid handle issued from the lease-bound runtime.
For Agents
Add an adapter-level regression test around
SparqlHttpStore.getSystemRecordLaneControllerV1: create a managed lease, resolve its runtime, issue a valid active replacement handle with the same lifecycle binding, pass it to an open session'sapplyVerified, and assert the path reaches the atomic executor behavior rather than returningcapability-lostfor an unrecognized registry.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validated as a missing integration-evidence case rather than an identified runtime defect. Added the exact lease-issued-handle-through-adapter regression to #2154; the current direct runtime, adapter rejection, atomic executor, and live ownership gates remain green.