Skip to content

feat(security)!: ADR-0090 P1 breaking wave — position rename, profile removal, secure OWD default, principal/external spec shapes#2697

Merged
os-zhuang merged 9 commits into
mainfrom
claude/adr-0090-p1-breaking-wave
Jul 9, 2026
Merged

feat(security)!: ADR-0090 P1 breaking wave — position rename, profile removal, secure OWD default, principal/external spec shapes#2697
os-zhuang merged 9 commits into
mainfrom
claude/adr-0090-p1-breaking-wave

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Implements ADR-0090 P1 (docs/adr/0090, accepted in #2695) as one coordinated pre-launch breaking pass — no compatibility aliases (supersedes ADR-0057 D5/D7 alias discipline per the ADR). 158 files, mechanical where possible, semantic where it matters. Tracks #2696.

Renames (D3) — the word "role" leaves the platform

  • sys_rolesys_position · sys_user_rolesys_user_position (field roleposition) · sys_role_permission_setsys_position_permission_set (field role_idposition_id)
  • RoleSchema/defineRolePositionSchema/definePositionflat: the parent field is gone (hierarchy lives on the BU tree; the old walk queried a column that never existed, per ADR-0057 D5)
  • ExecutionContext.roles[]positions[]; EvalUser/CEL contract current_user.rolescurrent_user.positions (formula ROLE_* validators, RLS docs, all CEL doc examples); RLS policy field rolespositions; stack property roles:positions:; metadata kinds role/profileposition (profile kind retired); SystemObjectName.ROLEPOSITION; ADR-0068 builtin constants BUILTIN_ROLE_*BUILTIN_IDENTITY_* (values unchanged: org_admin etc.)
  • better-auth boundary untouched (the ADR's sole exception): sys_member.role, additionalOrgRoles, org_membership_level. The approvals plugin's role approver type also stays — it resolves through sys_member.role and is flagged in the ADR as boundary follow-up.

Profile removal (D2)

isProfile deleted from PermissionSetSchema and every fixture; isDefault narrows to the install-time suggestion semantics; appDefaultProfileNameappDefaultPermissionSetName (isDefault-only, interim wiring until the everyone position lands in P2).

Secure OWD default (D1) + vocabulary (D4) + external dial (D11 shape)

  • Enum reduced to the canonical four; legacy read/read_write/full no longer parse (fixtures updated).
  • effectiveSharingModel: a custom object with an owner field and no sharingModel now resolves private — the objectui#2348 incident shape ("unset OWD + C/R/U grant = silent org-wide read/write") is pinned by new regression tests, including fail-closed handling of unrecognised stored values. System objects keep their explicit ADR-0066 posture.
  • New optional externalSharingModel (external ≤ internal; default private) lands as spec shape.

Principal taxonomy shape (D10)

principalKind / audience / onBehalfOf added to ExecutionContext — shape only, evaluation semantics phase in with P2+.

Sharing recipients

roleposition, expanded via sys_user_position ∪ the better-auth membership transition source (new flat PositionGraphService); role_and_subordinates removedunit_and_subordinates now expands the business-unit subtree (finishes ADR-0057 D5's re-homing honestly).

Verification

  • Full monorepo build green (70 tasks).
  • Full test suite green across packages (spec 6669; plugin-sharing 75 incl. new D1/D4 regressions; formula 206; core/runtime/cli all passing). Two pre-existing flaky/timing tests verified unrelated and passing in isolation (metadata-core ReDoS timing budget under parallel load).
  • Generated translations patched in place per their file contract (keys + leaf values for the three renamed objects, four locales); stale isProfile form-translation blocks removed.

Out of scope (per ADR phasing)

P2 everyone/guest anchors · P3 linter/tiered gates/delegated admin · P4 explain/matrix gate · runtime consumption of externalSharingModel/onBehalfOf · objectui UI follow-ups.

🤖 Generated with Claude Code

https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H


Generated by Claude Code

… removal, secure OWD default, principal/external spec shapes

One coordinated pre-launch pass implementing ADR-0090 D1-D4 and the P1
spec shapes of D10/D11 (docs/adr/0090). No compatibility aliases.

Renames (D3): sys_role→sys_position (+assignment/binding tables and
fields), RoleSchema→PositionSchema (flat, parent removed),
ctx.roles→ctx.positions, current_user.roles→current_user.positions
(formula validators, RLS docs, CEL examples), stack roles:→positions:,
metadata kinds role/profile→position. better-auth boundary untouched
(sys_member.role, additionalOrgRoles, org_membership_level).

Profile removal (D2): isProfile deleted from PermissionSetSchema and all
fixtures; isDefault narrowed to an install-time suggestion;
appDefaultProfileName→appDefaultPermissionSetName (isDefault-only).

OWD (D1/D4/D11): enum reduced to the canonical four; custom objects with
an owner field and no sharingModel now resolve PRIVATE (fail-closed for
unrecognised stored values; system objects keep the public fall-through);
new optional externalSharingModel field (external ≤ internal, P1 shape).
Regression tests pin the objectui#2348 incident shape (unset OWD + C/R/U
grant must not read others' records).

Principal taxonomy (D10, shape only): principalKind/audience/onBehalfOf
on ExecutionContext.

Sharing recipients: 'role'→'position' expanded via sys_user_position ∪
the membership transition source; 'role_and_subordinates' removed —
'unit_and_subordinates' expands the BU subtree (ADR-0057 D5 re-homing,
replacing the walk over a parent column that never existed).

Translations patched in place per generated-file contract; conformance
matrix row updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 9, 2026 3:46am

Request Review

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 20 package(s): @objectstack/cli, @objectstack/core, @objectstack/dogfood, @objectstack/downstream-contract, @objectstack/formula, @objectstack/objectql, @objectstack/platform-objects, @objectstack/plugin-approvals, @objectstack/plugin-auth, @objectstack/plugin-email, @objectstack/plugin-hono-server, @objectstack/plugin-reports, @objectstack/plugin-security, @objectstack/plugin-sharing, @objectstack/plugin-webhooks, @objectstack/rest, @objectstack/runtime, packages/services, @objectstack/spec, packages/triggers.

117 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via @objectstack/core)
  • content/docs/ai/agents.mdx (via @objectstack/spec)
  • content/docs/ai/knowledge-rag.mdx (via @objectstack/core)
  • content/docs/ai/natural-language-queries.mdx (via @objectstack/core)
  • content/docs/ai/skills-reference.mdx (via packages/cli, @objectstack/spec)
  • content/docs/ai/skills.mdx (via @objectstack/spec)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli, @objectstack/spec)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli, @objectstack/rest, @objectstack/spec)
  • content/docs/api/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest, @objectstack/spec)
  • content/docs/api/index.mdx (via @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/api/wire-format.mdx (via @objectstack/runtime)
  • content/docs/automation/approvals.mdx (via @objectstack/plugin-approvals, packages/spec)
  • content/docs/automation/flows.mdx (via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx (via packages/cli, @objectstack/runtime, packages/spec)
  • content/docs/automation/hooks.mdx (via @objectstack/spec)
  • content/docs/automation/index.mdx (via @objectstack/spec)
  • content/docs/automation/webhooks.mdx (via @objectstack/core, packages/plugins/plugin-webhooks, packages/services, @objectstack/spec)
  • content/docs/automation/workflows.mdx (via @objectstack/spec)
  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/objectql, packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/core, packages/runtime, packages/spec)
  • content/docs/data-modeling/analytics.mdx (via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx (via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx (via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx (via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx (via @objectstack/formula, packages/objectql, @objectstack/spec)
  • content/docs/data-modeling/index.mdx (via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx (via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx (via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx (via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx (via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/deployment/index.mdx (via @objectstack/runtime)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/core, @objectstack/objectql)
  • content/docs/deployment/production-readiness.mdx (via @objectstack/plugin-auth, @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/deployment/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/deployment/vercel.mdx (via @objectstack/objectql, @objectstack/runtime)
  • content/docs/getting-started/build-with-claude-code.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/cli, @objectstack/plugin-auth, @objectstack/plugin-security, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx (via @objectstack/spec)
  • content/docs/kernel/cluster.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx (via packages/spec)
  • content/docs/kernel/index.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli, packages/services, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/kernel/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/core, @objectstack/objectql, @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/kernel/services.mdx (via @objectstack/core, @objectstack/objectql)
  • content/docs/permissions/access-recipes.mdx (via packages/plugins/plugin-security)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli, @objectstack/core, @objectstack/objectql, @objectstack/plugin-auth, @objectstack/plugin-hono-server, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx (via packages/dogfood, packages/plugins/plugin-security, packages/plugins/plugin-sharing, packages/rest, @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx (via packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx (via packages/plugins/plugin-security, packages/plugins/plugin-sharing, @objectstack/spec)
  • content/docs/permissions/profiles.mdx (via @objectstack/spec)
  • content/docs/permissions/roles.mdx (via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/plugin-security, @objectstack/plugin-sharing, @objectstack/spec)
  • content/docs/permissions/sso.mdx (via @objectstack/plugin-auth)
  • content/docs/plugins/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/plugins/anatomy.mdx (via @objectstack/core)
  • content/docs/plugins/development.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/plugins/index.mdx (via @objectstack/core, @objectstack/objectql, @objectstack/plugin-auth, @objectstack/plugin-hono-server, @objectstack/plugin-security, @objectstack/rest, @objectstack/spec)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/core, @objectstack/formula, @objectstack/objectql, @objectstack/platform-objects, @objectstack/plugin-approvals, @objectstack/plugin-auth, @objectstack/plugin-email, @objectstack/plugin-hono-server, @objectstack/plugin-reports, @objectstack/plugin-security, @objectstack/plugin-sharing, @objectstack/plugin-webhooks, @objectstack/rest, @objectstack/runtime, packages/services, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/protocol/diagram.mdx (via packages/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/core, @objectstack/spec)
  • content/docs/protocol/objectos/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/i18n-standard.mdx (via packages/services, @objectstack/spec)
  • content/docs/protocol/objectos/index.mdx (via @objectstack/core, @objectstack/objectql, @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/core, @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/cli, @objectstack/core, @objectstack/spec)
  • content/docs/protocol/objectos/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/plugins/plugin-sharing, packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/objectql, @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/formula, @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/core, @objectstack/objectql, @objectstack/plugin-approvals, @objectstack/plugin-auth, @objectstack/plugin-hono-server, @objectstack/plugin-security, @objectstack/plugin-webhooks, @objectstack/rest, @objectstack/runtime, @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/objectql, @objectstack/plugin-approvals, @objectstack/plugin-auth, @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx (via @objectstack/spec)
  • content/docs/ui/dashboards.mdx (via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/ui/forms.mdx (via @objectstack/spec)
  • content/docs/ui/index.mdx (via @objectstack/spec)
  • content/docs/ui/role-based-interfaces.mdx (via packages/plugins/plugin-security)
  • content/docs/ui/setup-app.mdx (via @objectstack/platform-objects, @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

… classification + downstream fixture

Liveness: GOVERNED kind role→position; liveness/role.json→position.json
(flat, parent dropped); permission ledger rowLevelSecurity.positions;
object ledger gains externalSharingModel as 'authorable' with the P1
shape-only rationale and the #2696 pointer. Downstream-contract sharing
fixture moves to the position recipient.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
…tion identifiers

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
…recipient enum, D1 grandfather stamps — dogfood 39/39 green

- app-plugin: stack section registration positions→'position' kind (the
  seeding gap: declared positions never reached the registry); standalone
  artifact surface roles→positions; CLI diff/stats keys.
- sys_sharing_rule.recipient_type runtime enum role→position (seeding
  inserted 'position' and was rejected by the stale enum), description
  updated to the BU-subtree semantics of unit_and_subordinates.
- ADR-0090 D1 grandfather stamps: explicit `sharingModel:
  'public_read_write'` on showcase/dogfood fixture objects whose isolation
  is RLS-owned or intentionally public (they carry an auto-injected
  owner_id, so the new unset⇒private default would owner-filter them).
- dogfood expectations updated to v2 semantics (recipient 'position';
  appDefaultPermissionSetName is isDefault-only).
- service-datasource test: explicit casts for Response.json() unknowns
  (latent, surfaced by the affected-package typecheck).

Full dogfood suite 39 files / 191 tests green; repo-wide typecheck clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
claude added 2 commits July 9, 2026 03:15
…sition rename; runas/authz test fixtures to v2 field names

The spec export surface intentionally changed (RoleSchema→PositionSchema,
definePosition, ShareRecipientType 'position', ExecutionContext.positions,
principal-taxonomy fields, externalSharingModel) — snapshot regenerated per
the gate's documented flow. Test fixtures updated: sys_user_position rows
use the 'position' field, sys_position_permission_set uses position_id,
automation trigger identity uses positions[].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
… (v2 vocabulary)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
claude added 2 commits July 9, 2026 03:30
…ntics, multi-org benchmark recalibration

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
…— overlay whitelist guards, option-visibility positions, standalone surface

role/profile kinds asserted as retired (reintroduction guards per ADR-0090
D2/D3); position asserted allowOrgOverride:true. customSession projection
tests read user.positions. Standalone artifact surface tests use positions[].

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H
@os-zhuang
os-zhuang marked this pull request as ready for review July 9, 2026 03:57
@os-zhuang
os-zhuang merged commit 6d83431 into main Jul 9, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the claude/adr-0090-p1-breaking-wave branch July 9, 2026 03:58
os-zhuang added a commit that referenced this pull request Jul 9, 2026
…on Model v2 vocabulary (ADR-0090) (#2717)

- roles.mdx → positions.mdx: flat positions (岗位), assignment BU anchor,
  built-in identity positions, everyone/guest audience anchors; the
  hierarchy narrative moves to business units.
- profiles.mdx → migration tombstone: the Profile concept was removed
  (D2); maps each former use to everyone-anchor bindings, isDefault
  suggestions, and position-bound sets.
- permission-sets.mdx: rewritten as the single capability container —
  union semantics, access depth (moved here from profiles), capabilities,
  built-in sets (additive member_default baseline), governed assignment
  tables, isDefault suggestion, adminScope delegated administration,
  package provenance.
- sharing-rules.mdx: OWD default corrected to fail-closed private (D1 —
  the page previously documented the pre-v2 fail-open default), canonical
  four values only, externalSharingModel dial (D11), recipient types
  position / unit_and_subordinates / team.
- authorization.mdx: position vocabulary, D1/D11 in the enforcement
  chain, delegated-admin gate in anti-escalation, new explain-engine
  section (D6), D7 linter + access-matrix snapshot added to governance,
  ADR-0090 in the index.
- permissions-matrix.mdx: role-hierarchy section replaced with
  business-unit hierarchy & positions; isProfile removed from samples;
  position recipients.
- permission-metadata.mdx: isProfile → isDefault/adminScope in the field
  table; union-semantics section replaces Profile-vs-Set;
  current_user.positions.
- index.mdx: five-concepts overview, v2 implementation-status callout,
  best practices and example updated.
- access-recipes.mdx / field-level-security.mdx: link + heading fixes.

Authoritative reference: docs/design/permission-model.md; decision
record: ADR-0090 (P1 #2697, P2 #2708, P3 #2711, P4 #2716).


Claude-Session: https://claude.ai/code/session_012oLzaP8n7A3YKFmgaHWC8H

Co-authored-by: Claude <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 9, 2026
…90 v2 launch window (#2719)

The Release workflow's "Downstream backward-compat smoke (live hotcrm)"
gate has been red on every main commit since ADR-0090 P1 (#2697), which
removed the sharing recipients `role` / `role_and_subordinates` from
@objectstack/spec with no compatibility aliases (docs/adr/0090 D3). The
latest published hotcrm tag (v1.2.2) still authors those recipients, so
the gate necessarily fails on a break the spec took deliberately, and no
adopting hotcrm release exists yet to bump HOTCRM_REF to.

Mark the step continue-on-error so it keeps running for signal but no
longer blocks the v2 publish. Restore hard-blocking (drop the flag and
bump HOTCRM_REF) once hotcrm ships a release on the v2 recipient
vocabulary.


Claude-Session: https://claude.ai/code/session_016ZGeuMQ4SeuCR4uaiWTUX5

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants