Skip to content

[engine] Record an attestation window: attest_due_ts on asset_attestations and instrument_attestations #718

Description

@eaitbrahim

Context (verified 2026-09-04, on main at the #717 merge)

#701's Positions view shipped items 1–4. Its attestation chip did not, because two of the things it asks for are not recorded anywhere.

1. There is no expiry to read. The chip is specified as Attested: Q2-2026 · Purif: 0.38% turning into RE-ATTESTATION REQUIRED "when the quarterly filing window expires". Neither per-asset table records a due date:

  • asset_attestations (v6): asset, sector, backing, pays_yield, source, attested_by, attested_at
  • instrument_attestations (v10): venue, product_id, wrapper, source, attested_by, attested_at

Both carry attested_at and stop there. Two of the four attestation-bearing tables in the schema — broker_subscriptions and venue_cash_postures — do carry an explicit attest_due_ts alongside their attested_at, so the pattern exists here and these two were written without it. (venue_trade_scopes carries neither; it tracks attested_ts/confirmed_ts/refuted_ts instead.)

2. There is no denominator for the ratio. PurificationReport.owed_by_asset gives a per-asset USD figure that is real and recorded. A percentage needs something to be a percentage OF — owed against position value? against total income? against the asset's own realised proceeds? — and that choice is a judgement, not a lookup. Nothing on the report holds it.

Deriving either at read time is the failure mode this codebase names directly: a number invented for the UI. Same reasoning that split #715 out of #700.

Scope

  1. Schema bump, following the standing pattern (v17/v18/v19/v20 — DDL in _SCHEMA_STATEMENTS, a numbered, documented no-op step, SCHEMA_VERSION bumped):
    • asset_attestations.attest_due_ts INTEGER
    • instrument_attestations.attest_due_ts INTEGER
    • NULL means "no expiry recorded", never "expired" and never "valid forever". Every row written before this bump was made without anyone stating a window, and stamping one now — in either direction — would manufacture the claim the column exists to hold. venue_cash_postures and broker_subscriptions are the shape to copy.
  2. Write it at attestation time, wherever upsert_asset_attestation / upsert_instrument_attestation are called from, so the window is the attester's statement rather than a constant applied later. The quarterly cadence matches the pinned-quarterly-snapshot decision recorded on keel-broker-alpaca Phase B: equities paper profile, attestation semantics, runbook #370.
  3. Decide the purification figure (a decision, not code): either define the denominator upstream so a ratio can be computed by a report and read by the page, or accept owed_by_asset's dollars as what the chip shows. Dollars are honest today and need no engine change.

Refusals

  • No backfill of attest_due_ts, for the reason above.
  • No derivation of the expiry from attested_at + one quarter at read time. That is a global policy constant standing in for a per-row fact, and it is precisely the posture the two tables that got this right deliberately avoided — a window belongs to the attestation that was made, not to whatever the current default happens to be when someone opens a page.
  • No purification percentage until its denominator is defined and held by a report.

Then

The chip becomes a read: attested_at + attest_due_ts → attested / due-soon / RE-ATTESTATION REQUIRED, styled the way _ENTRY_GATE_STATES styles the freshness chip beside it, plus owed_by_asset in dollars. That closes the last of #701's original scope.

Acceptance

  • Fresh DB stamps the new version; the prior version migrates cleanly; re-running is idempotent.
  • A newly written attestation records the window it was made under; rows written before the bump read NULL and render as "no expiry recorded" rather than as either expired or valid.
  • Tests: migration idempotence, NULL-means-unrecorded on pre-bump rows, and an expired window rendering the warn state.

Split out of #701, where both were found to be unbuildable as specified.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    complianceShariah/compliance screening or policy (Compliance & rails)featureNew capability (groups under Features)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions