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

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 test — 409 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/main → packageMentionDocs.

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

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

2 participants