Confirmations on Finance's three Round 6 asks; _opex_allocation_rule and _opex_kind are encodable, operator-input-outside-silver is architecturally fine with one qualifier, v2.0.x manifest sequence matches Platform compute-readiness with one homing question
Summary
All three asks in 2026-05-19-finance-round-6-next-silver-asks-response are confirmed. The OPEX field names land cleanly under the existing registry pattern, with one structured-vs-notes choice Finance should weigh; operator-input outside silver is consistent with the firewall+silver architecture provided one constraint holds; and the v2.0.x manifest sequence matches Platform's compute-readiness order. One homing question Platform owes Finance: where do this round's two new beta metrics (contribution_margin, pnl_summary) land in the v2.0.x sub-section topology.
Ask 1: _opex_allocation_rule and _opex_kind are encodable
Confirmed, with two complementary encoding paths depending on whether the field is metric-level or per-row.
Metric-level / section-level declarations (_opex_allocation_rule: native_grain_plus_revenue_share_for_cross_grain): the registry pattern today is to declare _* policy fields in the metric entry's notes field as free text. This is how _attribution_model: linear lives on attribution_multi_touch, how _cash_pooling_model: pooled_at_organization lives on the runway/cash-position note, how _concentration_n: 10, _concentration_window_weeks: 52 lives on revenue_concentration. The current pnl_summary registry entry already has a note slot; adding _opex_allocation_rule: native_grain_plus_revenue_share_for_cross_grain to that note is a one-line edit Platform will land alongside the v2.0.x manifest landing for pnl-summary (or whatever sub-section absorbs it; see the homing question below).
This works but is unstructured. If Finance prefers a typed slot so the policy is machine-readable from /api/mart/sections/finance/schema rather than parsed out of free-text notes, Platform can extend SectionMetricEntry with an optional policy: Record<string, string> field that surfaces the _* declarations in the schema endpoint payload. Cheap to do; small typecheck-friendly extension; useful for downstream consumers that want to read the policy programmatically. Finance can choose: stay in notes (zero-cost, current pattern), or graduate to a typed slot (small Platform-side lift, surfaces in the schema endpoint).
Per-row tagging (_opex_kind: native_grain | cross_grain_revenue_share_allocated | structurally_unallocated_held_at_portfolio on each pnl_summary row): the current pnl_summary emits as a typed PnlSummaryRow in the pnl grouping under FinanceComputeResult, not as scalar LiveMetricRow. The grouping shape is fully extensible — adding opex_kind and (for tracing) opex_allocation_rule_applied as additional columns on PnlSummaryRow is a small, well-defined code change Platform will land when the OPEX allocation logic wires. Same pattern for operating_margin when it's added.
Naming convention call: the typed-row columns drop the leading underscore (so the column is opex_kind, not _opex_kind). The _* leading-underscore form stays the canonical name in the contract manifest text and in the policy-level declarations; the row column is the named version of that policy applied. This matches how MarginRow carries gross_margin_cents (not _gross_margin_cents) while the surrounding contract talks about _gross_margin as a contract concept. Finance can override this if a different convention is preferred.
Both paths are open. Platform's recommendation: notes for the metric-level policy; typed columns on the row shape for per-row tagging. The structured policy: registry slot is available if Finance wants it as a v2.0.x manifest deliverable.
Ask 2: operator-input outside silver is architecturally consistent, with one constraint
Confirmed. The firewall+silver model in the spec gates per-domain imports from third-party systems (Hubspot, Stripe, Calendly, etc.) into the per-domain silver face — it doesn't speak to cross-domain Finance's own internal data. Finance, as a cross-domain reading section per ADR-0015 + ADR-0016, is not required to land all its inputs in someone's silver before composing them. Operator-input feeds for opening balances and material movements living in a Finance-owned table are consistent with the architecture.
The one constraint: the operator-input data needs to live in a Finance-owned, versioned, queryable Postgres table that Finance's compute reads deterministically from. Same period + same input → same output, with audit trail. The shape of that table is documented in the v2.0.x cash-position.md manifest so consumers can reason about the input.
What Platform pushes back on (so the boundary is explicit): ad-hoc operator-recording shapes that aren't versioned or queryable from Finance's compute — for example, a Google Sheet that an operator hand-edits, or one-off spreadsheets emailed to Finance. Those break reproducibility and make /api/mart/sections/finance non-deterministic. If Finance's initial operator-recording path is anything like that as a stopgap, flag it; Platform can scope a small Finance-owned admin UI for the operator to record opening balances and material movements (a Finance-domain "operator entries" table behind a Finance-domain admin route, similar in posture to the existing audit-log inputs). The operator-recording stays on Finance's side of the boundary; Platform doesn't own the data model for those entries, just the routing path if Finance wants UI scaffolding.
The Revenue-silver-derived operational inflow/outflow is fine as documented (existing cross-domain warehouse access, no firewall expansion). When Revenue's revenue_deferred_release_schedule and refund_type silver faces land, Finance's compute refines via the standard cross-domain join — also fine.
The composite source declaration _cash_position_feed: composite_revenue_silver_plus_operator_recorded is encodable in the manifest text the same way as the other _* declarations. The v2.0.x cash-position.md manifest carries it.
Ask 3: v2.0.x manifest landing sequence matches Platform's compute-readiness
Confirmed. The proposed sequence is exactly the order Platform's compute is ready in.
| Sub-section manifest | Live compute today (Round 6) | Status |
|---|---|---|
unit_economics.md |
revenue_per_active_student beta, revenue_concentration beta |
Ready to land |
cac_payback.md |
cac_per_first_lock beta; cac_payback_weeks and payback_distribution gated |
Partial, ready |
ltv.md |
None; gated on cost-of-service silver + Sales cohort identity at gross-margin grain | Gated |
cohort_summary.md |
None; gated on encoding confirmation and revenue_earned_by_cohort / revenue_paid_by_cohort compute (not yet wired) |
Gated |
customer-journey-audit.md |
None; gated on the §8.4 carve-out's row-shape implementation | Gated |
Finance's "priority by compute readiness" framing matches what Platform is shipping. The two manifests with live compute (unit_economics.md, cac_payback.md) can land in the next Finance push; the three gated manifests land as their compute develops, with no Platform-side dependency on the ordering.
One small note on cohort_summary.md: Platform's read of the §8 spec text is that cohort-grain financial views fit naturally inside unit_economics (the cohort dimension is already one axis of the unit-economics view). If Finance prefers a separate cohort_summary sub-section, that's fine — Platform doesn't object — but the migration-under-unit_economics path Finance flagged as the alternative is also fine. Finance's call; no Platform action either way.
One homing question Platform owes Finance
Round 6 wired three new beta metrics in lib/mart/sections/finance.ts:
contribution_margin(lives in themargingrouping withgross_margin; metric_id namespace continuing themargin.*family)pnl_summaryv0 (newpnlgrouping; per-org + portfolio rollup;operating_expense_centsandnet_income_centsnull pending OPEX allocation)cac_per_first_lock(newcac_paybackgrouping; source-class split; cohort floor 5)
Finance's v2.0.x manifest topology names unit_economics.md, cac_payback.md, ltv.md, cohort_summary.md, customer-journey-audit.md. Platform reads the registry comment table at the top of lib/mart/registry.ts against this list and sees:
cac_per_first_lockclearly lands incac_payback.md. No question.contribution_marginreads as belonging inmargin.md(the existing v2.0.0 sub-section that already coversgross_marginandgross_margin_rate_bps). Finance v2.0.x can extendmargin.mdrather than spawning a new manifest. Platform reads the existingmargin.mdto confirm this is the intent.pnl_summaryis the one that doesn't have an obvious home in the named topology. The v2.0.0 README has apnl_summarysub-section name (referenced in the finance.ts code comment as "Per finance-mart v2.0.0 §8 pnl sub-section"); does Finance's v2.0.x landing sequence include apnl-summary.mdmanifest in addition to the five names enumerated in this round's response memo? Or doespnl_summarymigrate underunit_economics.mdor under a new sub-section name?
If pnl-summary.md is part of the v2.0.x landing schedule but was omitted from this round's enumeration of the five manifests, Platform suggests adding it (priority: alongside unit_economics.md since its primary compute is already at beta). If pnl_summary is intended to live under a different existing manifest, name which.
This is a single yes/no question, not a blocker — Platform can keep pnl_summary referenced as "v2.0.x sub-section TBD" in the registry notes until Finance names the home.
What Platform does next
- Lands the
_opex_allocation_rule: native_grain_plus_revenue_share_for_cross_graindeclaration in thepnl_summaryregistry note as soon as Finance confirms (or self-confirms via default-accept). - Extends
PnlSummaryRowwithopex_kindandopex_allocation_rule_appliedcolumns when Finance's OPEX allocation compute wires up. - Renders the
policy:structured registry slot if Finance picks the "graduate to typed slot" option from ask 1; no-op otherwise. - Continues to expose
cash_position_centsrow shape inCashPositionRowas documented; ready to scaffold a Finance-domain admin UI for operator-recording if Finance wants it. - Updates the registry note for
pnl_summaryonce Finance names the manifest home.
Asks back at Finance
- Confirm or override the encoding-path recommendation: notes-only for
_opex_allocation_rule(zero-cost), or structuredpolicy:slot (small Platform lift, machine-readable). If structured, Platform adds the slot. - Name the operator-recording substrate posture: existing Finance-owned table that Platform should be aware of, or a future scaffold Finance will scope, or "Platform please scaffold a Finance-domain operator-entries admin UI."
- Name
pnl_summary's home in the v2.0.x topology:pnl-summary.md(sixth manifest in the schedule), or migrated under one of the five named manifests (and which), or "still TBD" (Platform parks the note).
Silence by 2026-06-09 is default-accept; Platform reads it as: notes-only (cheapest path), Finance-owned operator table exists or will be scoped Finance-side without Platform UI scaffolding, and Finance will name pnl_summary's manifest home in the v2.0.x landings as they file.
References
- Parent:
2026-05-19-finance-round-6-next-silver-asks-response(the three asks) - Round 6 compute deliverables:
lib/mart/sections/finance.ts(PnlSummaryRow,CacRow, extendedMarginRow);lib/mart/registry.ts(pnl_summary,cac_per_first_lock,contribution_marginall at beta) - Registry pattern for
_*declarations in notes:attribution_multi_touch(_attribution_model: linear),revenue_concentration(_concentration_n: 10, _concentration_window_weeks: 52) - Encoding shape:
SectionMetricEntryinlib/mart/types.ts;PnlSummaryRowandFinanceGrouping<Row>inlib/mart/sections/finance.ts - Architectural basis: ADR-0015 (Finance/Portfolio as cross-domain reading domains), ADR-0016 (firewall mechanism)