1.2.0-rc.1 / Evidence and duties

Storage contracts

Signed storage sessions, checkpoints, omissions and closure.

Contract and accounting profile for 1.2.0-draft.3. Profile identifier: storage_sessions_v1. Selected agreements, signed collection, managed execution and portable free evidence implement the bounded runtime path separately from these accounting rules. This page forms part of the implementation candidate described in release status.

Explicit selection and exact fields

Both emitter and collector must explicitly select this profile. The top-level event_profile property is required and covered by the event signature. A draft.3 version alone does not select it. Existing draft.2 events and ordinary draft.3 free events retain their closed contracts and must reject these additional fields. The selected agreement integration binds reporting_profile:"storage_sessions_v1" in request, exact offer, signed acceptance and signed receipt; it never infers selection from a permissive parser or downgrades failed session reports to completed actions.

The event contains all ordinary draft.3 report fields plus event_profile:"storage_sessions_v1". This scoped profile accepts only event_type:"use.reported", source:"client_reported", one action, and null http, quantity and unit. It adds no automatic duration charge or payable quantity. Asset references remain explicit and may be null; a URL alone is not an immutable asset/version claim.

The closed operation object is exactly:

id, started_at, ended_at, state, kind, copy_context, storage

kind is action or storage_session. An action retains the existing in-progress/completed/failed semantics and has storage:null. A non-store action has copy_context:null. Every store action and storage session carries:

{
  "copy_id": "<UUIDv4>",
  "acquired_at": "<whole-second UTC>",
  "retain_until": "<whole-second UTC or null>",
  "parent_write": null
}

When this is a copy, parent_write is a qualified reference {reporter_id,event_id,payload_digest} to the exact authenticated completed parent write. Initial acquisition time is still a client assertion, not an independently observed fact. A verified chain establishes consistency of that assertion, not the existence or absence of undisclosed copies.

A storage session has exactly actions:["store"], no derived_from entries, and one related_events reference to its own completed write. It has a different operation ID from that write. Its copy_context, publisher/service/issuer/delegation, reporter, policy, agreement, resource, asset reference and purposes remain fixed. The write completion time equals the session’s started_at. One reporter/copy ID cannot name multiple write operations or multiple sessions.

The session’s closed storage object is exactly {trigger,checkpoint_index,scheduled_at}:

Trigger State and timing
start in_progress, null end, index 0; scheduled, occurred and started times equal the observed write completion timestamp.
checkpoint in_progress, null end, positive index n; scheduled time is original session start + n × 86,400 seconds. Actual occurrence is at or after that schedule, within its corresponding daily interval.
cessation completed, null index; scheduled, occurred and ended times equal the reported observed cessation time.

There is no failed terminal session that implies deletion. Failed or uncertain cleanup leaves custody open/unresolved. A checkpoint cannot occur at or after cessation. A completed write is never reopened as a session.

Accepted terms and retained-copy inheritance

The pure reducer takes one externally authenticated duty context:

terms = {
    "agreement_id": "<UUIDv4 or None for a static-policy duty>",
    "report_deadline_seconds": 300,
    "retention_seconds": 600,        # None when absent
    "use_expires_at": "<UTC>"       # None when absent
}

The adapter must derive these values from the applicable accepted agreement/policy and selected reporting endpoint; it must not accept a reporter’s substitute terms. For each copy, retain_until must equal the earlier of acquisition + retention seconds and accepted use expiry. Null is valid only when both limits are absent. Parent and child copy references must resolve by exact bytes and authenticated reporter identity, with matching scope, original acquisition time and deadline. Missing, altered, cyclic or overlong parent evidence remains unresolved. The bounded chain limit is 64 writes; batches contain at most 4,096 intake records.

An expired or zero-retention custody assertion can remain evidence of a client’s claim. The reducer exposes overdue custody; it grants no permission to perform that storage. It does not convert an overdue deadline into an automatic deletion event. Different agreement contexts must be reduced separately; cross-agreement copying is not inferred by this profile.

Reporting deadlines and coverage

Start and cessation reporting deadlines use their trigger times. Checkpoint deadlines use the original scheduled time, never a late observation or retry time. A verified intake received exactly at its deadline is timely. A report received afterward is late. An expected report with no qualifying intake is pending through its deadline and missing after it.

A late wake can report its current index with its actual observation time. It cannot manufacture reports for earlier intervals. If actual cessation occurs exactly at a checkpoint boundary, that boundary’s checkpoint is discharged; earlier gaps remain. When cleanup fails and the copy remains, the checkpoint still becomes due. Custody beyond the retention deadline remains visible even when access has expired.

Every known session with consistent, resolved write context contributes expected checkpoints through as_of or its reported cessation. A missing start report is exposed separately and does not remove its known schedule from the denominator. Contradictory session identity or unresolved write/parent evidence is counted in an unresolved cohort, excluded from resolved coverage and never labelled complete. Reports received after as_of cannot repair the historical denominator. Exact retries preserve one event; different bytes under one reporter/event ID conflict. All distinct conflicting variants remain in quarantine accounting, deduplicated per exact payload, so arrival order cannot hide a session or change the retry count. No conflicting variant can resolve a write reference. A different event ID for an occupied session trigger/index also conflicts.

The public metrics distinguish completed action claims, sessions known/started/closed, unresolved sessions and expected/timely/late/missing/pending checkpoints. Session cessation does not add a completed action. Missing/pending indices use compressed inclusive ranges, avoiding allocation of one row per day for arbitrarily old claims. An unusually large reporting deadline beyond the supported four-digit-year calendar is represented in analytical output as deadline_at:null with deadline_after_supported_calendar:true; integer duration comparisons still determine timeliness. Claimed session duration is not a measurement of continuous activity, bytes consumed, model use, or billable time.

Wire timestamps are whole-second UTC. The managed executor preserves original high-resolution acquisition/cleanup observations and uses conservative retention rounding. Its integration guide specifies the less-than-one-second conservative cessation bound when two ordered observations share a wire second. Passing whole-second semantic tests is not proof of timer precision or physical erasure.

Implemented APIs and verification

profiles/storage_sessions.py provides validate_event(value) and:

reduce_records(records, as_of=utc_time, terms=terms, expected_binding=B)
# record = {payload: exact_bytes, received_at: verified_collector_time,
#           authenticated_reporter_id: verified_reporter_identity}

expected_binding, when supplied, is exactly the ordinary five-field draft.3 binding. The trusted adapter must verify reporter signature, collector signature/time, current or retained authority as appropriate, and exact intake payload before supplying records. Merely labelling an input authenticated_reporter_id does not authenticate it. Do not mix intakes from different reporting endpoints to manufacture the earliest successful delivery. The reducer validates the profile and then reuses unchanged ordinary report semantics on a deliberately normalized internal copy; it never accepts legacy wire bytes as this profile.

verification/storage-session-verifier.mjs independently implements event semantics and verifyStorageSession(records,{asOf,terms,expectedBinding}) for one session plus exact write/parent evidence. It uses native Node and the separately implemented strict JSON primitives; it imports no Python validator. Unlike the batch reducer’s quarantine output, it rejects contradictory or unresolved evidence. Neither API performs physical observation or cryptographic authentication itself.

Executed checks: 26 Python tests, 14 independent Node tests, and 11 shared wire cases (5 positive, 6 negative) accepted/rejected consistently by strict AJV and the Node semantic validator. Commands:

PYTHONPATH=tests:. python3 -m unittest test_storage_sessions -v
node --test verification/test_storage_session_verifier.mjs
node verification/storage-session-verifier.mjs profiles/fixtures/storage-session-cases.json
node verification/check_profiles.cjs /absolute/path/to/ajv profiles/fixtures/storage-session-cases.json

The original structural results are retained as component evidence. Current validation records the combined agreement, collector, executor and selected archive checks. Native assets, paid storage portability and provider handover have separate contracts and evidence; these accounting tests alone do not establish those capabilities. See release status for publication gates.

Odexa / Protocol explorer

This page. Your terms.

Inspect this website’s published policy and see how a proposed use is evaluated.

Current pagehttps://odexa.io/releases/1.2.0-rc.1/docs/storage-sessions/
Loading policy…

Published JSON
Open JSON

This is a local policy check, not a signed agreement or proof of agent compliance. Other published licences and applicable rights still apply. How policy evaluation works →

Odexa / Get in touch

Start a conversation.

Tell us what you have in mind. We’ll respond where we can.

We use these details to review and respond to your enquiry. Please leave out confidential information. Submitting does not subscribe you to marketing. Privacy policy.