Skip to content

docs(spec): TenantPlanSchema doc block states the entitlement-layer fold, not normalization (#9345) - #9492

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-9345-tenantplan-docblock
Aug 18, 2026
Merged

docs(spec): TenantPlanSchema doc block states the entitlement-layer fold, not normalization (#9345)#9492
os-steve merged 1 commit into
mainfrom
claude/issue-9345-tenantplan-docblock

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#9345

What changed

TenantPlanSchema's doc block (packages/spec/src/cloud/tenant.zod.ts:47-50)
claimed the free-tier fold for unrecognized plan codes was "the cloud
distribution's normalization." That was measured wrong on the citation and
on the mechanism, per cloud#1380's ruling (2026-08-16) and its landing in
cloud PR #1417 (merged 2026-08-17). Doc-block prose only — no schema or
behaviour change; TenantPlanSchema still accepts any string.

Before (packages/spec/src/cloud/tenant.zod.ts:47-50)

 * Convention (not enforced here): an empty or unrecognized value is treated
* as the free tier by cloud-side readers. Spec accepts any string, including
* the empty one — the free-tier fallback is the cloud distribution's
* normalization, not a spec-level default.

After (packages/spec/src/cloud/tenant.zod.ts:47-69)

 * Convention (not enforced here): as of the cloud#1380 ruling (2026-08-16,
* landed in cloud PR #1417, merged 2026-08-17), an empty or unrecognized
* value folds to the free tier on **both** cloud-side mirrors (the
* control-plane `planKey` reader and the tenant-runtime `isFreePlan`
* reader). The fold happens at the **entitlement layer**, not in
* normalization: `sys_environment.plan` keeps the raw value (case-normalized
* only), so an unrecognized tier stays distinguishable from the free tier to
* any reader, log line, or operator — cloud#1389's red line is normalize the
* spelling, never the vocabulary. Spec accepts any string, including the
* empty one — the free-tier fallback is a cloud-side entitlement decision,
* not a spec-level default.
*
* The two mirrors' vocabularies are **not** merged into one list: cloud#1380
* lands A over a copy of the vocabulary, pinned to the source by an
* element-for-element equality guard. Unifying them is cloud#1418 (ruled,
* not yet landed) — and even once it lands, a SHA-pinned image can still
* predate a vocabulary entry, so the two lists can disagree either way.
*
* The fold's premise is operational, not structural: new plan tiers are
* minted rarely, and images roll before a new tier goes on sale. If that
* discipline changes, this premise changes with it (see the cloud
* distribution's `isFreePlan` docstring, which carries the same premise).

The three do-not-write traps (unlock comment, 2026-08-17T16:02Z) — each checked off

  1. Entitlement layer, never "normalized to free." The corrected text
    attributes the fold to isFreePlan (entitlement evaluation), states that
    sys_environment.plan keeps the raw value (case-normalization only), and
    cites cloud#1389's red line by name (normalize the spelling, never the
    vocabulary). It never uses the word "normalized" to describe the
    unknown-to-free fold.
  2. Two vocabularies stay two, not one list. The corrected text states
    explicitly that cloud#1380 lands over a pinned copy, that unifying them
    is cloud#1418 (ruled, not yet landed), and that even after feat(connector-slack): Slack Web API connector + connector/channel reconciliation (ADR-0022) #1418 lands a
    SHA-pinned image can predate a vocabulary entry.
  3. Operational premise carried, consistent with isFreePlan's docstring.
    New tiers are minted rarely and images roll before a new tier goes on
    sale; if that discipline changes, the premise changes with it — worded to
    not contradict the cloud-side docstring per the unlock comment (re-verified
    quote of the merged isFreePlan is the measurement of record; this repo
    cannot read the cloud repo directly).

Verification (all at head 102813d6b)

  • pnpm --filter @objectstack/spec build — clean.
  • pnpm --filter @objectstack/spec check:generated — all 13 generated
    artifacts up to date (the JSDoc block is not read by build-docs.ts; only
    .describe() strings are, and those are unchanged, so no regeneration was
    needed).
  • pnpm --filter @objectstack/spec typecheck — clean.
  • pnpm --filter @objectstack/spec test409 test files / 10915 tests
    passed
    , 0 failed.
  • Dispatch-derived local gates (node scripts/pm/dispatch-gates.mjs packages/spec/src/cloud/tenant.zod.ts), all green: check:cross-package-test-inputs,
    check:doc-formula-expressions, check:spec-parsed-alias,
    check:type-source-resolution, check:merge-driver, check:empty-state,
    check:variant-docs, check:dev-prereqs --self-test (the CI-run form —
    CI never runs the full-workspace scan directly, see the script's own
    header), check-affected-docs.mjs --self-test (its only CI-run form).
    check:strictness-ledger and check:liveness are covered inside
    check:generated above.
  • grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' over the changed files — clean.

Scope

packages/spec doc-block text only. No schema, validation, or behaviour
change — acceptance is byte-identical. Changeset: @objectstack/spec patch.

Generated-artifacts coupling

Wave-8 siblings: #9463, #9406, #9447 — landings serialize; a later lander
runs scripts/pm/os-regen-merge.sh per AGENTS.md §11 if a merge commit is
needed. This PR is left as draft; the PM lands it.


Generated by Claude Code

…old, not normalization (#9345)
TenantPlanSchema's doc block claimed unrecognized plan codes fold to free
via "the cloud distribution's normalization." That was wrong on the
mechanism and the citation as of the cloud#1380 ruling (2026-08-16),
landed in cloud PR #1417 (merged 2026-08-17):
- The fold happens at the entitlement layer (isFreePlan), not in
normalization -- sys_environment.plan keeps the raw value (case-
normalized only), so an unrecognized tier stays distinguishable from
the free tier to any reader, log line, or operator (cloud#1389's red
line: normalize the spelling, never the vocabulary).
- Before the ruling, only the control-plane planKey reader folded
unknown to free; the tenant-runtime isFreePlan reader granted paid
access. As of cloud PR #1417 both mirrors fold.
- The two mirrors' vocabularies are not merged into one list (cloud#1380
lands over a pinned copy; unifying them is cloud#1418, ruled but not
landed, and a SHA-pinned image can predate a vocabulary entry even
after that lands).
- Carries the ruling's operational premise -- new tiers are minted
rarely, images roll before a new tier goes on sale -- consistent with
cloud's isFreePlan docstring.
Doc-block prose only. No schema, validation, or behaviour change --
TenantPlanSchema still accepts any string; acceptance is byte-identical.
Fixes#9345
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fs18A2DdXLVN2h8PaaFBcP
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/src/cloud/tenant.zod.ts) — pages documenting those are invisible to this run

Coarse fallback — 113 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json origin/mainpackageMentionDocs.

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

Labels

documentationImprovements or additions to documentationsize/stooling

Projects

None yet

2 participants

@os-steve@claude