Skip to main content
POST
Seal a review submission

Authorizations

Authorization
string
header
required

MeshQu API key passed as a bearer token: Authorization: Bearer mqu_…. Mint one in the console (Settings → API keys).

X-MeshQu-Tenant-Id
string
header
required

Tenant UUID for multi-tenant isolation. Required on all authenticated routes — validated before authentication (middleware/tenant.ts), so a missing or non-UUID header returns 400 (MISSING_TENANT_ID / INVALID_TENANT_ID) before the API key is checked.

Path Parameters

id
string<uuid>
required

Policy id.

version
integer
required

Policy version number.

Required range: x >= 1

Body

application/json

Everything needed to assemble the ten ruled component slots. Four slots — the corpus (source_manifest_items / source_units), clause_ledger, candidate_policy and source_rule_map — must be genuinely present: a source-bound review package with no corpus, ledger, candidate or map is not one, and every totality and bidirectionality rule over it would be vacuously true.

Everything needed to assemble the ten ruled component slots. Four slots — the corpus (source_manifest_items / source_units), clause_ledger, candidate_policy and source_rule_map — must be genuinely present: a source-bound review package with no corpus, ledger, candidate or map is not one, and every totality and bidirectionality rule over it would be vacuously true.

source_manifest_items
required
source_units
required
clause_ledger
required
candidate_policy
required

The candidate policy as projected into the package. Any field beyond candidate_rules is carried VERBATIM into the component and therefore into its digest — the assembler adds nothing and removes nothing.

source_rule_map
required

The bidirectional source-to-rule map. BOTH directions are stored and must be exact transposes. Storing one and deriving the other would make disagreement impossible to observe: two directions that must agree is a check, one direction plus a derivation is a restatement.

assumptions
required
internal_controls
required
case_pack
required

Independently authored cases and expected outcomes. Carried verbatim into the digest.

validation_results
required

The displayed server/tool validation results. Separated from case_pack deliberately, so changing a RESULT changes the review subject rather than silently reusing the digest of the expectations alone.

case_execution_results
required

The displayed case-execution results. Separated from case_pack for the same reason.

model_trace
required

The model trace, as shown. Carried verbatim into the digest.

prior_source_manifest_items
object[]

The source_manifest_items of the immediately preceding sealed submission, when one exists. Present ONLY so "the bytes moved while the declared identity stayed still" is detectable. It is not part of any component and never enters a digest.

Response

Default Response

id
string<uuid>
required

The submission’s own identity — distinct per submission even when the policy version and the bytes are unchanged (ruling B1).

tenant_id
string<uuid>
required
policy_id
string<uuid>
required
policy_version_id
string<uuid>
required

The mutable workflow container the candidate came from. NOT the review identity: one policy version yields many sealed subjects over time.

candidate_revision
integer
required

A server-derived counter of DISTINCT CONSECUTIVE active-rule projections sealed for this policy version, starting at 1. It increments when the new submission’s active_rules_hash differs from the previous submission’s, and carries forward when it does not. Named for what it counts: meshqu.policy_versions holds no draft revision counter, so this is NOT a count of author edits and does not move for an edit that leaves the active-rule projection unchanged (a renamed rule, a changed description, a different case pack). Two submissions may therefore share a candidate_revision and still be different subjects — they are told apart by id and review_package_digest, which is why the currentness check has three legs.

Required range: x >= 1
submission_sequence
integer
required

Submission ordinal within the policy version, from 1. An ORDERING fact, not an identity — id is the identity.

Required range: x >= 1
review_package_digest
string
required

sha256(UTF8("meshqu-review-package/v1") || 0x00 || UTF8(canonicalJsonV2(envelope))). RECORDS which exact canonical bytes the reviewer was shown. PROVES byte equality under that named profile and nothing else — not source truth, completeness, correct interpretation, human review or authority. NOT a receipt field.

Pattern: ^[0-9a-f]{64}$
component_digests
object
required

The ten ruled component digests, keyed by component name. A closed registry: an eleventh key is invalid and a missing key is invalid.

active_rules_hash
string
required

sha256(canonicalJson(projectActiveRules(rules))) under meshqu-canonical/v0 — NOT v2, and deliberately OUTSIDE the ten component slots (ruling D2), so that comparing it against a recomputation from the product path is a real check rather than one artefact validating itself. It means "this is the projection the evaluator will run", which is a different claim from the package digest’s "these are the bytes a human read". Neither implies the other.

Pattern: ^[0-9a-f]{64}$
sealed_at
string<date-time>
required

When the seal was created. Not when a human read it.

sealed_by
string
required

The principal the server attributed the submit act to. Records attribution; proves nothing about human authorship, competence or independent judgment.