5.6 KiB
| id | type | title | domain | repo | status | owner | topic_slug | created | updated | state_hub_workstream_id |
|---|---|---|---|---|---|---|---|---|---|---|
| ADAPTIVE-WP-0010 | workplan | Plan-derived guardrail spend ceilings | financials | adaptive-pricing | proposed | codex | helix-forge | 2026-08-18 | 2026-08-18 | 38613963-4455-4e0c-849f-65fdda68f572 |
Plan-derived guardrail spend ceilings
Give tenant-engine's guardrail resolver a commercial feed, so a tenant's
monthly spend ceiling derives from the plan it holds rather than from a
headcount band that nobody signed off on.
Offered by tenant-engine on 2026-08-17 alongside the TEN-WP-0010 grouping
change (tenant-engine/docs/tenant-guardrail-policy.md, TEN-WP-0006). The
precedence layer already exists in their resolver — a plan-derived limit
outranks a grouping default — and it has no feed today.
Position
The problem is ownership, not mechanism. Ceilings currently resolve from
tenant:<grouping>:<name>'s middle segment. Reclassifying a tenant from small
to enterprise moves its ceiling from EUR 250 to EUR 20,000. That is a
commercial fact wearing operational clothing: tenant-engine states plainly
that every non-trial value is a conservative opener they chose so no grouping
started unbounded, and that nobody has approved them commercially. Only
trial = 0 is canon, from ADR-0013.
This is the same shape the tenancy framework was written to stop — a
customer-affecting commercial commitment resolved by an operational default
with no recorded owner. adaptive-pricing owns plan terms, so this is ours to
feed.
A plan is a better basis than a band. The grouping is a proxy for size; the plan is the actual agreement the customer entered. Deriving a blast-radius limit from what someone bought is more defensible than deriving it from what bracket their headcount fell into at onboarding — particularly now that grouping is mutable (TEN-WP-0010) and the identifier's middle segment is historical rather than authoritative.
Two constraints, stated up front because they shape the design.
A ceiling is a guardrail, not a price. The moment a limit derives from plan terms there is pressure to present it as an entitlement the customer purchased. That is a different product with different obligations — an entitlement implies we will serve up to it, a guardrail only says we will stop beyond it. The design must keep them distinguishable, and the customer-facing wording must not promise capacity.
A ceiling change is a commercial event. It goes through the tier-terms
approval path rather than resolving silently, consistent with SCOPE.md on
customer-visible pricing changes and with the ADAPTIVE-WP-0009 T04 gate.
Not yet agreed with tenant-engine. They offered the conversation; we said
yes in principle and flagged it as new scope. Nothing here is committed until
T01 produces a shape both repos accept.
Establish The Interface Contract With tenant-engine
id: ADAPTIVE-WP-0010-T01
status: todo
priority: high
state_hub_task_id: "7109ccf7-1267-44b6-9f20-38eff7bb7dd2"
Agree the shape of the feed jointly with tenant-engine: what
adaptive-pricing publishes, what their resolver consumes, and what happens on
stale or missing input.
Open questions to settle, not to assume:
- Is the ceiling a field on the pricing model, or a separate derivation from it? A tier's ceiling is not obviously one of its charge components.
- What resolves for a tenant whose plan carries no ceiling — the grouping default, or a refusal? Falling back silently reintroduces the problem.
- Which side holds the number when they disagree?
ADAPTIVE-WP-0009's answer for assurance claims was that the tier definition is authoritative and other records derive from it; the same logic likely applies, but say so explicitly. - Does a plan change mid-period move the ceiling immediately or at renewal? This is a commercial answer, not a technical one.
Record the outcome as a decision, since it binds two repos.
Extend The Pricing Schema With Ceiling Terms
id: ADAPTIVE-WP-0010-T02
status: wait
priority: medium
state_hub_task_id: "7da0b8f5-93a7-4048-900d-8fa39eb0de96"
Blocked on T01.
Add the agreed representation to the canonical schema. Follow the
assurance_claims precedent from ADAPTIVE-WP-0009-T02: optional, typed,
defaulted, so every existing model stays valid and silent tiers keep resolving
from the grouping default until deliberately migrated.
Keep the guardrail/entitlement distinction structural rather than a comment — if the field is named or shaped like an allowance, it will be read as one.
Validate Ceiling Coherence
id: ADAPTIVE-WP-0010-T03
status: wait
priority: medium
state_hub_task_id: "82788fbd-e0e7-4bb0-94ca-405176e74809"
Blocked on T02.
Boundary-engine rules, explainable in the existing style:
- A ceiling below the tier's own expected usage is incoherent — the tier would stop the customer doing what they paid for.
- A ceiling must not be presented in customer-facing wording as capacity.
- A tier with usage-based components and no ceiling is a declared choice, not an oversight; require it to be explicit.
Route Ceiling Changes Through Approval
id: ADAPTIVE-WP-0010-T04
status: wait
priority: medium
state_hub_task_id: "c9220137-baed-4ba1-929c-449ba1a754b9"
Blocked on T02.
Extend the ADAPTIVE-WP-0009-T04 governance gate so a tier acquiring or
changing a ceiling raises a blocking approval requirement at tier definition,
carrying the prior and proposed values. Reuse the existing comparison
machinery rather than adding a second gate; as with assurance claims, it must
stay a definition-time review and not become a per-campaign one.