Skip to content

fix: framework producers on tenant-column objects name the organization they can derive (ADR-0131 D9, C8 stage 8b-0b) - #24369

Merged
objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-24343-producers-name-organization
Oct 18, 2026
Merged

objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-24343-producers-name-organization

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Part of #24343
Part of #15212
Clause-②: yes (widening)

C8 stage 8b-0b (plan 6251466182 on #15212). Before stage 8b lifts the system-insert exemption, each framework producer that writes organization-less rows on a tenant-column object now names the organization it can derive itself (ADR-0131 D9: derived under single, refused otherwise). Under single that organization is the Default Organization, which is the owner the engine would derive, so no reader changes. Under a wall a row is stamped only where the producer has an organization. A row it cannot attribute is written exactly as before, and its fate stays the engine's (stage 8b). This PR does not lift the exemption and does not retire any NULL reader.

Why Part of #24343 and not Fixes. #24343's acceptance is "0 NULL rows on the three tables after a sign-up on a walled control plane, and the ceremony's advisory count reads 0". The walled half cannot be met by naming a derivable organization, because a sign-up has none to derive (measured below). Reaching it takes the fate decisions listed under "Not built". Merging this PR must not close the card.

Why Clause-②: yes (widening) when the claim said no. Three exported types gain optional members: AuditWriterOptions.getDefaultOrganizationId (plugin-audit), and organization_id on SettingsSecretStore.insert's row and organizationId on SettingsAuditWriter.write's entry (service-settings). These are additive widenings of a published surface, so those two packages take minor. Nothing narrows. buildSettingAuditWriter's optional logger was briefly narrowed on this branch (head bc7e2b791, { error?; warn }), and the contract review caught it (record 6253189824). It is now { warn? } | { error; warn? }: main's accept set (no sink, {}, { warn? }) plus a sink that carries error. A tsc probe of those four shapes plus a typed { error?; warn? } passed, then the probe was deleted. check:optional-error-sink and check:durability-log-level exit 0.

Measured first (framework at this branch, in-process sqlite, examples/app-crm)

A sign-up through POST /auth/sign-up/email with the audience opened (audience_posture: open, declared set member_default), then one global encrypted settings write (mail.api_key). Rows written after the snapshot:

table single (this PR) isolated (multiTenant: 'posture-only', this PR)
sys_user_permission_set 1 written, 0 without an organization 1 written, 1 without (the registrant's grant)
sys_email 1 / 0 1 / 1 (the verification mail)
sys_activity all stamped with the Default Organization 12 / 12: activity about sys_user (created, updated), sys_email (created, updated), sys_user_permission_set, sys_platform_setting ×3, sys_setting_audit ×3, sys_secret
sys_secret (D4) — 1 / 1 (the global mail.api_key ciphertext)
sys_setting_audit (D4) — all 6 rows in the table without an organization, all scope: global
  • A1. No organization is derivable for any of the three sign-up writers under a wall: the registrant belongs to no organization when its grant, its verification mail and the activity about its user row are written. The activity rows are about records that have no organization (sys_user, sys_platform_setting, sys_secret …) or that are org-less for the same reason. Under single, the verification and reset mails and the activity about org-less records used to land NULL, and they now carry the Default Organization. The grant already carried it.
  • A3 / D4. The deployment-level population under a wall is not empty. All 17 encrypted settings declared in this tree are scope: global (ai ×10, auth, knowledge ×2, mail, sms ×2, storage), so every sys_secret row the settings producer writes from the built-in catalog is deployment-level. The datasource binder's credential rows are deployment-level by construction. No webhook producer writes sys_secret. Every global-rung write lands an org-less sys_setting_audit row.

What changed

  • plugin-auth (auth-manager.ts). One reading, derivableWriteOrganizationId(), which is tenancy.defaultOrgId(): the Default Organization under single, none under a wall. It feeds the self-registration grant (settleSelfRegistrationGrant) and the five auth mails about a user: verification, password reset, account invitation, magic link and the change-email notice.
  • plugin-audit (audit-writers.ts, audit-plugin.ts). An activity row whose record has no organization, written with no session organization, takes getDefaultOrganizationId(). AuditPlugin wires that to the tenancy service. The record's own organization and then the session's still win, and the ledger's tenant_id attribution (D7) is untouched.
  • service-settings (settings-service.ts, settings-service-plugin.ts, settings-service.types.ts). The sys_secret ciphertext and the sys_setting_audit row of a tenant or user value carry that value's organization, the same owner as its sys_setting row. A global value's rows name none (D4, below). The setting-audit writer's catch now reports at error when the sink carries it (else warn), under the degradation log-level rule: the settings write succeeds while the history row is lost. Without this a refusal from stage 8b would be a silent audit loss. The first report carries the consequence and the fix.
  • verify (rls.ts). The RLS probe and position personas' grants belong to the persona's single membership, which under single is the Default Organization. They were written with an explicit organization_id: null.
  • dogfood fixture (showcase-bu-hierarchy-sharing.dogfood.test.ts, the "fixture :66"). Its findOne('sys_organization', { where: {} }) is refused by the engine as an arbitrary pick. The .catch(() => null) swallowed that refusal, so the fixture always minted a stand-in org_bu beside the real Default Organization. It now reads the Default Organization from the tenancy service, and it stamps its sys_business_unit_member rows too.

Not built — fates ADR-0131 D7/D9 do not settle (reported to the seat)

  1. The walled self-registration grant (the registrant has no organization yet).
  2. The walled auth mails about a user (sys_email).
  3. The walled activity about org-less records (sys_activity).
  4. D4: the deployment-level sys_secret (global settings secrets, datasource credentials) and sys_setting_audit (global rung) rows. No object leaves the tenant-column set here.

The ceremony's advisory count (packages/cli) is not touched. It reads 0 for these tables only once 1–3 are decided.

Tests

  • New plugin-auth/src/producers-name-organization.test.ts: the verification mail, the reset mail and the grant, each under single (Default Organization) and under a wall (none).
  • plugin-audit/src/audit-writers.test.ts: three cases. The Default Organization is used under single; none under a wall, with no resolver, or when the resolver throws; a known organization is never overridden and the resolver is not asked.
  • New service-settings/src/settings-secret-organization.test.ts: tenant value vs global value, and the audit writer's organization_id. settings-user-reference.pin.test.ts follows the error channel.
  • verify/src/rls-persona-grant.test.ts: the persona with one membership, none, and two.
  • New dogfood/test/signup-organization-census.dogfood.test.ts: the single half of ADR-0131 D9 on a walled control plane: three framework writers land NULL organization_id rows on every sign-up (the self-registration grant, the verification mail, activity about org-less records) #24343's acceptance census. After a real open-audience sign-up, every row the sign-up wrote on the three tables names the Default Organization. The platform admin's promotion grant, which is stage 8b-0a's, is set aside by snapshot.
  • Ablation (census, plugin-audit, through scripts/ablation-replace.mjs with a trap, then a rebuild): the fallback's resolver returned undefined (return ['ABLATED'][1]). ablation-dist-preflight found the marker in dist, and the census went red (sys_activity: rows without an organization, 2 rows). Restored: blob equal to HEAD, git diff HEAD empty, --absent preflight passed, 2/2 green.
  • Package suites at 5c3cbdd90: plugin-auth 161 files / 3123 passed, 10 skipped; plugin-audit 56 / 897; service-settings 50 / 874; verify 41 / 363. typecheck passed for all four packages and for dogfood. Dogfood journeys passed 6 files / 28 tests: the census, the business-unit sharing fixture, rls-fixture, admin-identity-audit-trail, settings-organization-isolation and email-template-materialization.

Gates

node scripts/pm/dispatch-gates.mjs --commands derived 77 families; all were run and reconciled with --ran (76 run, 1 NOT MEASURED). The NOT MEASURED one is check:dual-build-cjs-loads, which exited 3 (PREREQUISITE NOT MET: no full pnpm build on this box), so CI's reading counts for it. check:engine-double-contract was red once, on a findOne in the new grant double. It was fixed by dropping the member the writer never calls, and the re-run passed. check-plugin-teardown-shape --self-test needed its pinned commit fetched (shallow clone) and then passed. The family list re-derived after the last commit is identical.

Acceptance notes

🤖 Generated with Claude Code

https://claude.ai/code/session_015nNHWXUVqXs5TqaLtf2aGt


Generated by Claude Code

…n derive (ADR-0131 D9)

The self-registration grant and the auth mails about a user read one
derivable organization (the Default Organization under single); the
activity writer falls back to it for a record with no organization; the
settings secret and setting-audit rows carry their setting's owner; the
verify RLS personas' grants carry the persona's membership; the business
unit dogfood fixture stops swallowing its organization read.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nNHWXUVqXs5TqaLtf2aGt
… Default Organization

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nNHWXUVqXs5TqaLtf2aGt
@github-actions github-actions Bot added size/l documentation Improvements or additions to documentation tests tooling labels Oct 18, 2026
@github-actions

github-actions Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/plugin-audit, @objectstack/plugin-auth, @objectstack/service-settings, @objectstack/verify, touching 16 documentable anchor(s).

11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/deployment/environment-variables.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/deployment/tenancy-modes.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/kernel/contracts/auth-service.mdx (via AuthManager (symbol, a top-level class))
  • content/docs/kernel/runtime-services/settings-service.mdx (via setMany (symbol, a method of class SettingsService))
  • content/docs/kernel/services-checklist.mdx (via AuthManager (symbol, a top-level class))
  • content/docs/permissions/authentication.mdx (via AuthManager (symbol, a top-level class), sys_member (literal, a string literal in personaOrganization))
  • content/docs/permissions/delegated-administration.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/permissions/permission-sets.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/permissions/positions.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/permissions/system-context.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/protocol/kernel/config-resolution.mdx (via setMany (symbol, a method of class SettingsService))

⛔ 7 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/implementation-status.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/releases/v14.mdx (via setMany (symbol, a method of class SettingsService))
  • content/docs/releases/v16.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/releases/v17/17-0.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/releases/v17/17-1.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/releases/v17/17-3.mdx (via sys_member (literal, a string literal in personaOrganization))
  • content/docs/releases/v17/17-6.mdx (via sys_member (literal, a string literal in personaOrganization))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 3 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 25 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 41c7405364be55d302191f55b9301ef96cb7f432 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from a5e15d3c99fc453c4911737b7b3ae1f5f98a330f — the merge of head 02778102c241db46c2a17dfc6deb0cca927d32b9 into base 41c7405364be55d302191f55b9301ef96cb7f432, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin a5e15d3c99fc453c4911737b7b3ae1f5f98a330f && git checkout a5e15d3c99fc453c4911737b7b3ae1f5f98a330f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 41c7405364be55d302191f55b9301ef96cb7f432 02778102c241db46c2a17dfc6deb0cca927d32b9 && git checkout -B drift-repro 41c7405364be55d302191f55b9301ef96cb7f432 && git merge --no-ff 02778102c241db46c2a17dfc6deb0cca927d32b9

node scripts/docs-audit/affected-docs.mjs --json 41c7405364be55d302191f55b9301ef96cb7f432

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 41c7405364be55d302191f55b9301ef96cb7f432 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

…llback for a reduced logger

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nNHWXUVqXs5TqaLtf2aGt
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: bc7e2b791614910e115b8d96919a1cfc6575860e
Local-runs: none

Rendered in-seat by the epic seat (epic:#15194) · 2026-10-18T17:54Z. This is the declaration face. reviewFace on the 15 committed paths finds no published schema and no governed path, so only the Clause-②: yes (widening) line owes this review, at TIER_DEFAULT.

Read: card #24343 and its comments (claim 6251523047, report 6252315398, addendum 6253007344); the PR body; the net diff origin/main...bc7e2b791 (15 files, +656/−29); the exports maps and entry files of @objectstack/plugin-audit and @objectstack/service-settings; and the head's check-runs. Nothing was built or run.

Check-runs on the head: 40 in all. 31 success, among them Lint & Repo Gates, Check Changeset, Governed Surface Queue Guard, every Type Check · lane and Build Core. 6 skipped by design. 3 Test Core shards were still in_progress at the read. 0 failure. The verdict does not depend on the open shards.

① Derived judgments

  1. buildSettingAuditWriter's logger parameter narrows. The declaration is wrong here.
    • buildSettingAuditWriter is exported from @objectstack/service-settings's . entry (src/index.ts:75).
    • On main its second parameter is logger?: { warn?: (message: string) => void }. On the head it is logger?: { error?: (message: string) => void; warn: (message: string) => void }.
    • A caller that passes {}, a sink typed { warn?: … }, or a sink with only error type-checks on main and is refused on the head. That shrinks a published accept set.
    • The PR body says "Nothing narrows". The changeset clause "(the argument stays optional; a sink passed to it declares warn, as PluginContext.logger does)" describes the narrowing without naming it as one.
    • The only in-tree caller (settings-service-plugin.ts:547, ctx.logger as any) is unaffected, so CI stays green. The declaration answers for the accept set, not for the in-tree callers.
  2. AuditWriterOptions.getDefaultOrganizationId?, a new optional member. Widening. Right. The interface is the opts parameter of installAuditWriters, which plugin-audit's . entry exports (src/index.ts:11), so the change is on the published type graph. An optional member on an input type accepts every value it accepted before.
  3. organization_id? on SettingsSecretStore.insert's row and organizationId? on SettingsAuditWriter.write's entry. Widening. Right.
    • Both types are reachable through the exported SettingsServiceOptions (secretStore?, auditWriter?, settings-service.types.ts:375/:379).
    • An implementer written against main still satisfies both, because the argument it receives only gains an optional member.
    • A custom store that ignores the new member keeps writing rows without an organization. The changeset scopes the claim to the built-in writers, which is accurate.
  4. The behaviour-only changes have no type effect. Right under D9. They cover plugin-auth (derivableWriteOrganizationId: the self-registration grant and the five auth mails), verify (personaOrganization) and the plugin-audit activity-row fallback.
    • Each names an organization only where one is derivable, and otherwise writes exactly as before.
    • Under single, the organization named is the Default Organization, which is the owner the engine derives.
    • The extra reads are bounded. personaOrganization does one sys_member find per persona (limit 2). The audit fallback asks defaultOrgId() only for a row whose record and session both lack an organization.
  5. Changeset sentences checked against the diff.
    • The plugin-auth bullet is true. On main, the verification and reset mails passed no organizationId, even under single.
    • The plugin-audit bullet is true.
    • The service-settings bullet is true, except for the narrowing clause in item 1.
    • The verify bullet is true: the explicit organization_id: null is gone from both persona grants.

② Semver level

  • Consistent with items 2 to 4. @objectstack/plugin-audit and @objectstack/service-settings are minor for the widenings. @objectstack/plugin-auth and @objectstack/verify are patch for behaviour.
  • Not consistent with item 1. A narrowing in @objectstack/service-settings needs three things: the yes (narrowing) arm, the ADR-0087 disposition that the registration gate names, and a review at CONTRACT_REVIEW_TIER on the narrowing face.
  • Check Changeset and Lint & Repo Gates read the line as written. A narrowing that is not declared passes them.

③ Boundary flags

Remedy

The dev picks one remedy, measured, and says why in the PR.

  • A (recommended). Restore the parameter's accept set from main, then report at error where the sink carries it.
    • One shape that may pass both gates: logger?: { warn?: (message: string) => void } | { error: (message: string) => void; warn?: (message: string) => void }. The first member declares no error, so it is outside the sink gate's population. The second declares error as required, so there is nothing to guarantee.
    • Run pnpm check:optional-error-sink and pnpm check:durability-log-level on the shape. If either refuses it, report what the gate says rather than trying a third shape.
  • B. Keep the narrowing and declare it: Clause-②: yes (narrowing) on both the PR body and the changeset, plus the ADR-0087 disposition, then a review at CONTRACT_REVIEW_TIER. Not recommended: no caller needs the narrowing.

Under either remedy, rewrite the changeset clause in item 1 so it says what the head does.

Implemented-by: session_015nNHWXUVqXs5TqaLtf2aGt
Reviewed-by: session_01Y5583bs2RDd53MH6kM1ca3

VERDICT: FAIL

…et and takes an error-carrying sink beside it

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015nNHWXUVqXs5TqaLtf2aGt
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 02778102c241db46c2a17dfc6deb0cca927d32b9
Local-runs: none

Rendered in-seat by the epic seat (epic:#15194) · 2026-10-18T18:25Z. This is the declaration face, as in record 6253189824. reviewFace on the committed paths finds no published schema and no governed path, so only the Clause-②: yes (widening) line owes this review, at TIER_DEFAULT.

Read:

Nothing was built or run.

Check-runs on the head: 47 in all.

  • 36 success, among them Lint & Repo Gates, Check Changeset, Governed Surface Queue Guard, every Type Check · lane, Build Core, and the claim and single-writer guards.
  • 8 skipped by design.
  • 2 cancelled: the first runs of No other open PR may claim the same single-writer path and Part-of PR must not also close its card. The PR-body edit superseded them, and their reruns on this head are success (check-runs 117748136862, 117748132683).
  • 1 Test Core shard, 3/6, was still in_progress at the read.
  • 0 failure.

The verdict does not depend on the open shard. Landing waits for it.

① Derived judgments

  1. buildSettingAuditWriter's logger no longer narrows. Right.
    • The parameter is now logger?: { warn?: (message: string) => void } | { error: (message: string) => void; warn?: (message: string) => void }.
    • The first member is exactly main's published type. So every value main accepted is still accepted: none, {}, a typed { warn? }, and, by structural assignability, a typed { error?; warn? }.
    • The second member adds an error-only sink. This is a widening, inside the line already declared.
    • At runtime, report() writes to error only when the sink carries one as a function ('error' in logger && typeof logger.error === 'function'). Otherwise it writes to warn?.(). A sink with neither stays silent, exactly as on main.
    • The union keeps no error? member without a non-optional warn, so check:optional-error-sink has nothing to refuse. The dev measured exit 0, and Lint & Repo Gates is green on this head.
  2. Items 2 to 4 of record 6253189824 stand unchanged. They are AuditWriterOptions.getDefaultOrganizationId?, the two optional members on the settings store and writer, and the behaviour-only producers. The delta does not touch them.
  3. The rewritten changeset sentence is true against the diff. It reads: "buildSettingAuditWriter's optional logger argument keeps every sink it accepted (none, {}, or one with an optional warn) and additionally takes a sink that carries error. It reports through error when the sink has it, else through warn." The other changeset sentences are unchanged and were checked in record 6253189824.
  4. The PR body's declaration paragraph is now true. It records the brief narrowing at bc7e2b791 and its removal.

② Semver level

  • @objectstack/plugin-audit minor and @objectstack/service-settings minor match the widenings.
  • @objectstack/plugin-auth patch and @objectstack/verify patch match behaviour-only changes.
  • Clause-②: yes (widening) on the PR body and the changeset is now true: nothing on the published surface narrows.
  • No breaking change, so no ADR-0087 disposition is owed.

③ Boundary flags

Implemented-by: session_015nNHWXUVqXs5TqaLtf2aGt
Reviewed-by: session_01Y5583bs2RDd53MH6kM1ca3

VERDICT: PASS

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/l tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants