Skip to content

validation: make Rubin executor the canonical draw-payload digest owner #516

Open

Description

@seonghobae

Finding

#515 adds a per-run complete_data_draws_sha256 commitment to the public activation receipt and requires the runtime digest independently. That prevents payload substitution if both values come from the canonical execution payload. The current executor, however, does not yet compute or emit that digest itself; a caller can still invent the hash input representation.

A content digest has scientific/audit value only when its serialization and filtering semantics are owned by the same application boundary that admits the rows used by the Rubin computation. Otherwise two consumers can hash the same numerical matrix differently, or a caller can hash pre-cutoff/pre-transposition bytes that do not match the values actually passed to psychometric_core.

Required repair

Make analysis_engine the canonical owner of the concrete complete-data draw-payload digest after cutoff/snapshot admission and before numerical combination.

Use a versioned, domain-separated deterministic binary representation rather than locale/JSON formatting:

  • digest only the admitted complete-data indicator draw matrix actually passed to psychometric_core;
  • preserve exact draw order and admitted observation order;
  • bind observation count and draw count;
  • encode finite f64 values by stable IEEE-754 bit pattern in fixed byte order;
  • late rows excluded by AvailableTime > KnowledgeCutoff must not alter the historical digest;
  • changing any admitted draw value must change the digest;
  • carry the resulting canonical lowercase SHA-256 in the digest-bound Rubin artifact with a read-only accessor and canonical-format validation;
  • future activation should consume this executor-produced artifact digest rather than rely on an ad hoc caller serialization.

Do not infer approved-generator execution from this digest. It is canonical payload identity, not generator attestation. Do not copy Rubin arithmetic out of psychometric_core.

RED target

For identical snapshot/cutoff and eligible draws, adding only a future-unavailable row must preserve complete_data_draws_sha256. Changing one eligible draw value while preserving snapshot, row count, draw count, indicator kind, and cutoff must change it. Artifact import must reject malformed/noncanonical digest values.

Lifecycle

Implement on Draft #506 as an ordinary forward repair, keep ADR 0034 Proposed, keep production activation registry empty, and hand the complete source/test/docs delta to #416/#435. Do not close until exact-head hosted evidence and surviving-vehicle inheritance are verified.

Activity

  1. seonghobae commented on Sep 14, 2026

    @seonghobae
    ContributorAuthor

    Repair is now on Draft #506 through exact head 40fb4f6764afc0a32eb246bb27348c4c23ed7532. RED fcd1c0c97594dac319dc4da12a5c09625abf4d78 established cutoff-safe/value-sensitive executor ownership. Causal source/artifact repair d4404370d012d214891cf24b4a79688ecd58b845 computes the digest after snapshot/cutoff admission and draw-major transposition, before psychometric_core, using domain tepp.rubin_loading.complete_data_draws.v1\0, admitted observation/draw counts as big-endian u64, and exact finite f64 IEEE-754 bits in big-endian order. The lowercase SHA-256 is private/read-only in the Rubin artifact and artifact import rejects malformed values. Research and ADR are current through cd71c98f85eec396a4bf144da9148e11eb800186 → 40fb4f6764afc0a32eb246bb27348c4c23ed7532. This issue stays open until exact-head hosted Rust/docs/security evidence completes and #416 demonstrably inherits the full test/source/docs/ADR delta. A matching payload digest remains content identity, not approved-generator execution attestation.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions