# description
Per-cited-number attestation envelope for BI / conversational-analytics / spreadsheet-AI tools. Binds {natural-language query, source-table identity + version sha, transform chain sha, output number, dataset DID, runner DID} to a cryptographic chain that satisfies SOX 404 + PCAOB AS-1000 + AS-1105 audit-traceable-lineage for any number that drives a regulated decision (earnings, risk reporting, financial-disclosure docs). Closes SYNTHESIS-acquisition Round 21 P3 [[ai-spreadsheets-and-bi]] BI1 ship-first action. Today BI tools (Hex Notebook Agent, Sigma + Tableau Pulse + Power BI Copilot, ThoughtSpot Spotter Agents, Excel Copilot, Google Sheets Gemini =AI() function, Databricks AI/BI Genie, Snowflake Cortex Analyst) surface answers + visualizations from LLM-generated SQL — but the data lineage from raw DB → transform → chart → cited number lacks attested integrity. When a CFO asks 'how did Q1 revenue compare to forecast' and gets a chart, the AI-generated SQL + transform chain has no signed record. ip.bi.cited_number.attestation.v1 closes that gap. Composes with R14 D1 ipAttestationRunFacet (pipeline tier — dbt/Airflow/Spark/Flink runs upstream of the BI query) → R21 BI1 (this — cited number) → R19 A1 alignment-evidence (essay/argument citing the number downstream). dbt MCP server 8 toolsets Apr-2026 = natural integration point. One JSON Schema × every NLQ-BI / notebook-BI / spreadsheet-BI tool.

# $comment
Discovery: https://ip.tekton.cc/.well-known/ip-knowledge.json (full descriptor) | Badge: https://ip.tekton.cc/api/badge/v1/attestation/bi.cited_number.attestation.v1/<subjectSha256> (shields.io endpoint) | Free dry-run: POST https://ip.tekton.cc/api/credentials/dry-run with body {kind:"bi.cited_number.attestation.v1", body:<candidate>} (no auth required, validates against this schema) | Verification recipe: https://ip.tekton.cc/docs/verification-recipe.md (3-layer trust model + curl trail) | Revocation: https://ip.tekton.cc/credentials/status/v1 (W3C BitstringStatusList v1.0; check bit at credentialStatus.statusListIndex)

# properties.schemaVersion.description
Semver of this schema. Bumps to 2.0.0 land at /credentials/bi-cited-number/v2 — v1 stays immutable (see /docs/schema-versioning.md for the cycle-726 canonical bump-mechanics + soft-change-detection contract).

# properties.attestationId.description
Unique RFC 4122 UUID v4 or v7 — this attestation's canonical identifier. Lets a consumer dedupe across retries + replays and link this attestation back to a ip.attestation.event.v1 wire row via ipAttestationEventId.

# properties.biSurface.description
BI archetype that produced the cited number. 'nlq-bi' = natural-language query (ThoughtSpot Spotter, Tableau Pulse, Power BI Copilot, Sage). 'notebook-bi' = notebook-style analytics (Hex Magic, Mode under Analyst Studio). 'spreadsheet-bi' = AI inside a cell (Excel Copilot agentic, Google Sheets Gemini =AI(), Numerous AI, Equals, Rows). 'dashboard-bi' = scheduled refresh of a chart-driven view. 'metric-store' = dbt MetricFlow / Lightdash / Snowflake Cortex Analyst semantic-layer call. Different archetypes have different audit-trail requirements; this routes downstream verifiers.

# properties.tool.description
Stable handle for the BI tool. Examples: 'hex' / 'sigma' / 'thoughtspot-spotter' / 'tableau-pulse' / 'powerbi-copilot' / 'excel-copilot' / 'sheets-gemini' / 'databricks-genie' / 'snowflake-cortex-analyst' / 'dbt-metricflow' / 'lightdash' / 'looker-studio-pro' / 'metabase-x'. Lowercase + hyphen + digit so the value doubles as a URL slug + docker-tag fragment.

# properties.toolVersionSha256.description
Optional sha256 of the BI tool's release manifest at the time of the cited-number computation. Pins WHICH version of the tool generated the SQL + transform. For SaaS-only tools (Hex, Sigma, Tableau Pulse), the vendor MAY publish a build-id manifest that resolves to this sha — or this field is omitted and trust falls back on issuerDid + tool name.

# properties.naturalLanguageQuery.description
Optional human-readable natural-language query the user asked. When present, sha256(canonical(naturalLanguageQuery)) MUST equal querySha256 — where canonical() is JCS (RFC 8785) canonicalization of the JSON string VALUE (the quoted, backslash-escaped string), i.e. sha256 over the JCS bytes INCLUDING the surrounding quotes. ⚠ RECIPE PIN (cycle 1196, schema-prober sp-1196-P1): this is the JCS-quoted-string recompute (validator mode inline-payload-and-recompute), DISTINCT from the raw-UTF-8-bytes recipe (mode inline-text-utf8-bytes) used by retrieval.queryText / embedding.inputText / translation.sourceText, which hash the UNQUOTED raw bytes. Applying the raw-UTF-8-bytes recipe here produces a hard false-reject with no hint — JCS-serialize the string THEN sha256. Useful for in-line audit display but exposes the user prompt; omit when user-prompt privacy matters (querySha256 alone suffices for verification).

# properties.querySha256.description
Sha256 of the canonical natural-language query bytes (or canonical-JSON of the structured query object). Required. Pins the user's intent. Lets a downstream verifier confirm 'this number came from THIS question' without storing the question verbatim.

# properties.generatedSqlSha256.description
Optional sha256 of the canonical SQL the AI generated to compute the answer. When present + sqlText is also present, sha must match. The Snowflake Cortex Analyst 90%+ SQL-accuracy claim (R21 P3) and the Databricks AI/BI Genie + dbt MetricFlow paths all generate SQL from NLQ — attesting the canonical SQL pins WHICH JOIN PATH + WHICH FILTERS produced the answer (critical for SOX audit reproducibility).

# properties.generatedSqlText.description
Optional human-readable SQL. When present, sha256(canonical(generatedSqlText)) MUST equal generatedSqlSha256 — where canonical() is JCS (RFC 8785) canonicalization of the JSON string VALUE (the quoted, backslash-escaped string), i.e. sha256 over the JCS bytes INCLUDING the surrounding quotes. ⚠ RECIPE PIN (cycle 1196, schema-prober sp-1196-P1): JCS-quoted-string recompute (validator mode inline-payload-and-recompute), DISTINCT from the raw-UTF-8-bytes recipe used by retrieval.queryText / embedding.inputText / translation.sourceText — applying the raw-bytes recipe here false-rejects. JCS-serialize the string THEN sha256. Useful for auditor inline review (SOX 404 reproducibility); omit when SQL exposes proprietary schema or query patterns.

# properties.sourceTables.items.properties.snapshotSha256.description
Sha256 of the table snapshot at the moment of computation. For SCD-2 / time-travel tables (Snowflake Time Travel, Databricks Delta history, Iceberg snapshots): the canonical-JSON of (table_id, snapshot_id, query_timestamp). Pins WHICH ROWS contributed to the number.

# properties.sourceTables.items.properties.rowCount.description
Number of rows in the snapshot at computation time. Useful for downstream sanity-checks.

# properties.sourceTables.description
Array of source tables that contributed to the cited number, each pinned to its snapshot sha. Required for SOX 404 + PCAOB AS-1105 audit (the lineage from raw data → number). For metric-store tools (dbt MetricFlow / Snowflake Cortex), the metric definition resolves to underlying tables — surface ALL of them here so the chain is complete.

# properties.pipelineRunIds.description
Array of ip.pipeline.facet.v1 run IDs (R14 D1 ipAttestationRunFacet — OpenLineage facet) that produced the source-table snapshots. Chains UPSTREAM to the pipeline tier. When a CFO's auditor asks 'how was this number computed,' the chain walks: ip.bi.cited_number → pipelineRunIds[] → ip.pipeline.facet.v1 → upstream raw data.

# properties.transformSha256.description
Sha256 of the canonical transform chain applied to source-table rows to produce the cited number. For dbt MetricFlow: sha256 of the metric definition (including all referenced models). For ad-hoc SQL: sha256 of (generatedSqlSha256 ⊕ post-processing-script-sha). For Excel Copilot: sha256 of the formula chain. Pins the COMPUTATION SHAPE.

# properties.outputNumber.description
The cited number itself, serialized as a string to preserve precision across financial-domain edge cases (decimal places, currency, scientific notation, ratios, percentages). Examples: '1234567.89', '$4.2M', '0.847', '23.5%', '1.4e6'. String preserves the canonical display form the BI tool used; downstream consumers parse per their domain rules.

# properties.outputContextSha256.description
Sha256 of the canonical context the number was emitted in. For chart contexts: sha256 of (chart_type + axis_labels + filter_dimensions + group_by). For text contexts: sha256 of the surrounding sentence(s). Required because the SAME outputNumber can mean different things in different chart contexts; pinning the context defeats the 'I quoted the number but misrepresented its scope' failure mode.

# properties.computedAt.description
Epoch milliseconds when the BI tool computed the cited number. Required because BI answers are time-sensitive (revenue figures change as new transactions land; KPIs drift). The verifier walks: re-execute the canonical query against the pinned snapshots at computedAt — must reproduce.

# properties.publishedAt.description
Optional epoch milliseconds when the cited number was first published / shared (in a report, email, slide deck, regulatory filing). Distinct from computedAt for batch-refresh + scheduled-distribution workflows. When present, publishedAt >= computedAt.

# properties.issuerDid.description
DID of the entity issuing this attestation (the BI tool's signing identity OR an independent peer-verifier). did:web for institutional BI vendor (did:web:hex.tech, did:web:databricks.com); did:key for individual analyst / spreadsheet-author submission. When the issuer is the BI tool itself, the attestation is vendor-signed; when issuer is independent, it's peer-attested.

# properties.auditFlags.properties.sox404.description
True when this attestation is intended to satisfy Sarbanes-Oxley Section 404 audit-traceable-lineage requirements (relevant when the cited number drives a regulated financial disclosure).

# properties.auditFlags.properties.pcaobAs1000.description
True when this attestation is intended to support PCAOB AS-1000 (General Responsibilities) audit-evidence requirements.

# properties.auditFlags.properties.pcaobAs1105.description
True when this attestation is intended to support PCAOB AS-1105 (Audit Evidence) sufficiency + appropriateness standards.

# properties.auditFlags.properties.secAiDisclosure.description
True when this attestation is intended to support SEC AI-disclosure 2026 obligations (10-K disclosure of AI-driven financial-reporting workflows).

# properties.auditFlags.description
Optional regulatory-context flags. Signals to a downstream regulator-facing verifier WHICH audit framework the issuer intended the attestation to cover. Helps audit-tooling (R14 G1 governance line items) route the attestation to the right compliance framework.

# properties.judgesDigest.description
When this attestation results from a multi-judge peer review (3+ independent verifiers per CP's standard peer-review economy), the canonical digest of the judges manifest. Chains to the same judgesDigest field used in CP's brief/artifact/eval-result/sandbox-run/eval-run/synthetic-media/legal-citation manifests (cycle 303 derivationRecipes documentation applies).

# properties.ipAttestationEventId.description
When this attestation was emitted as a ip.attestation.event.v1 row (R11 T1) to the platform's Kafka/Tinybird/ClickHouse pipeline, the eventId of that wire row.

# properties.chain.properties.parentSha256.description
Sha256 of the canonical-JSON bytes of the parent attestation. For a bi.cited_number attestation the parent is either the ip.review.attestation.v1 of the peer-review pass that confirmed the citation chain (when this attestation results from a multi-judge review — cycle 303 derivationRecipes pattern) OR the ip.governance.compliance.v1 row covering the BI-citation policy (anti-fabricated-number substrate at the program level). ⚠ Cycle 493 honest-disclosure: platform does NOT verify parent-existence at issuance; consumers walk the chain against their own registry per /docs/verification-recipe.md.

# properties.chain.properties.parentKind.description
Kind identifier of the parent attestation. bi.cited_number tolerates review-attestation (peer-reviewed citation chain — judges signed off on the number) or governance-compliance (program-level anchor for BI/analytics-citation enforcement).

# properties.chain.properties.parentAttestationId.description
Optional UUID of the parent attestation — convenience for consumers that index by id rather than by sha256.

# properties.chain.description
Cycle 783 (sc-772-P0-1 partial close, batch A/3): uniform upward chain link per the cycle-484 substrate. Pre-cycle-783 bi.cited_number had no chain.parentSha256 — breaking the anti-fabricated-number traversal for BI/analytics citation contexts where a downstream auditor needs to prove which review pass or governance program authorized the number. The block is OPTIONAL (not in required[]) so back-compat is preserved.

# properties.signature.description
Ed25519 signature (128 hex chars = 64 raw bytes) over the canonical-JSON bytes of (attestationId ⊕ biSurface ⊕ tool? ⊕ toolVersionSha256? ⊕ naturalLanguageQuery? ⊕ querySha256 ⊕ generatedSqlSha256? ⊕ generatedSqlText? ⊕ sourceTables ⊕ pipelineRunIds? ⊕ transformSha256? ⊕ outputNumber ⊕ outputContextSha256 ⊕ computedAt ⊕ publishedAt? ⊕ issuerDid ⊕ auditFlags? ⊕ judgesDigest? ⊕ ipAttestationEventId?). Verify against the publicKey published in the issuerDid's JWKS. RFC 8037 (Ed25519 in JWS) canonicalization rules apply: JCS (RFC 8785) ordering on the inner object. ⚠ INTEGRITY GAP (aa-824-P0-1, cycle 848 honest disclosure): `chain.*` and `extra` are presently OUTSIDE this signature pre-image. A wire-path or post-hoc rewrite of `chain.parentSha256` / `chain.parentKind` / `chain.parentAttestationId` does NOT invalidate this `signature`. Offline verifiers using `signature`+`publicKey` (the documented embedded-verification path) MUST treat `chain.*` as ADVISORY pointer-shape, NOT cryptographically bound to this attestation. For full-integrity verification including chain pointers, fetch the W3C DataIntegrityProof envelope from /credentials/<sha>/v1 and verify against the proof.cryptosuite=eddsa-jcs-2022 signature (which signs the FULL canonical-JSON body including chain). Cycle-484 added the chain block; cycles 778-784 swept it; the signature pre-image was not re-derived. Migration target: v2 schema slug ($id pin per cycle-462). See cycles 825-829 (5/5 wedge-tier ring) + cycle 830 (verification-recipe.md dual-path teaching) for the canonical write-up; cycle 848 fans this disclosure to the 12 remaining chain-bearing leaf schemas in one batch.

# properties.publicKey.description
Ed25519 public key (32 raw bytes = 64 hex) corresponding to the signature above.

# properties.extra.description
Open extension slot — BI-tool-specific or analytics-workflow-specific payload (e.g., dbt MetricFlow metric definition JSON, Snowflake Cortex Analyst confidence score, Excel Copilot citation array). Consumers MUST ignore unknown keys.