Skip to content

docs(permissions): a recipe for "lock these fields for this role once the record reaches a stage" — the field permission when and its Studio column, in access-recipes and the administrator guide #26178

Closed

Description

@objectstack-fleet

Filing gate ③: a maintainer-directed task. The maintainer, in the triage seat thread on 2026-10-26, asked 「这一类的功能有文档吗?客户会知道和理解吗」, read the triage reading below, then said 「立卡」. Filed by the triage seat (session_01AavokzJ5DndAwitDXvKy4U, seat post #6015). ⛔ Not a claim.

Business reason: a row-conditioned edit lock (the field permission when, #25866, landed in #25980; Studio column in PR #26010) answers a need every business app meets: at this stage, this role may no longer change these fields. Examples are a contract's legal terms after approval, an order's amount after shipping, an invoice after posting, and a purchase order's supplier after approval. Today only the developer reference describes it. An administrator who meets the need finds neither the capability nor where Studio offers it, so they ask a developer for a hook, or settle for a validation rule that locks the field for everyone.

Reader who acts: the domain:docs lane, one PR.

Measured (origin/main, 2026-10-26)

Wanted

  1. A recipe in access-recipes.mdx: "Lock fields for a role once a record reaches a stage". Use the contract case (finance may edit drafts, but not the legal terms once status is approved or later), with:
    • the Studio path: permission set → field row → When (edit) → a condition such as status in ["approved", "signing", "active"];
    • the same entry as metadata (fields: { 'clm_contract.governing_law': { readable: true, editable: false, when: … } });
    • how to choose: a lock that holds for everyone is a validation rule; a lock that depends on who is editing is a field permission when.
  2. The boundaries, stated plainly:
    • it governs edit only, never read;
    • the condition names fields of the same object only;
    • on update it reads the record before the write, so a write cannot unlock itself by changing status in the same request;
    • it locks, it does not grant: another set that grants the edit still wins under the most-permissive merge (the muting/deny layer is the future answer).
  3. administrator-guide.mdx Step 5: one pointer sentence to the recipe.
  4. Link the recipe from field-level-security.mdx's when section.

Acceptance: pnpm check:doc-authoring and the link checker pass, and the recipe's metadata snippet parses (a doc-snippet pin, if the docs suite has one for recipes).

Dedupe: access-recipes.mdx and the open domain:docs cards list (#26087, #26088 and others) carry no card for this.


Generated by Claude Code

Activity

  1. added
    documentationImprovements or additions to documentation
    pm:queueReady for the PM dispatch loop
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    on Oct 26, 2026
  2. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — documentation · priority:p2 · domain:docs · area:access · pm:queue (as filed) · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-26T14:56Z

    ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  3. added
    domain:devxDomain lane — seat card indexed by label:pm:seat
    and removed on Oct 26, 2026
  4. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 5 · 2026-10-26T16:25Z
    Session: session_01Q4MDXRbEJCNdPAP4SiXwp9 (devx seat 2) · card thread session_01GEk1n2M6ejRZucZuYZLamJ
    Account: os-steve
    Branch: claude/project-thread-b3k4op (the harness-pinned branch of the card thread; it names no issue, so this claim is the identity record; amended on spawn)
    Worktree: objectstack-issue-26178
    Domain: domain:devx
    Seat: domain:devx#2 (seat post #20163)
    File surface: content/docs/permissions/access-recipes.mdx (one recipe), content/docs/permissions/administrator-guide.mdx (one pointer sentence in Step 5), content/docs/permissions/field-level-security.mdx (one link from the when section), plus a doc-snippet pin if the docs suite has one for recipes (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default tier (TIER_DEFAULT, from dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6419195264
    Premise: holds — the field permission when is on main (#25980) and its Studio column landed with PR #26010; access-recipes.mdx has no mention
    Serial constraints cleared: no open PR touches content/docs/permissions/**


    Generated by Claude Code

  5. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 26, 2026
  6. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26178,
      "status": "done",
      "branch": "claude/project-thread-b3k4op",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26251",
      "head": "70e79e2d",
      "session": "session_01GEk1n2M6ejRZucZuYZLamJ (card thread; dispatching seat session_01Q4MDXRbEJCNdPAP4SiXwp9)",
      "premise_still_valid": true,
      "summary": "Recipe 'Lock fields for a position once a record reaches a stage' added to access-recipes.mdx (contract case, editor path to When (edit), definePermissionSet metadata, validation rule vs field permission when, the four card boundaries), plus a layer-table row; administrator-guide Step 5 FLS bullet points to it; field-level-security when section links to it. The metadata block is a self-contained os:check example, so check:skill-examples now type-checks it.",
      "tests": "Recipe block parsed with PermissionSetSchema from packages/spec/src via a one-off tsx script (not committed): success true; negative control readable:false beside the same when refused at fields.clm_contract.governing_law.when with the schema's own message. Pin reverse check on committed head 70e79e2d: when renamed to whenn reds check:skill-examples (exit 1, TS2561 at access-recipes.mdx:67:70); restored via git checkout HEAD, blob 2c041d93 equals HEAD, git diff HEAD empty. No package code touched, so no package test/typecheck owed.",
      "gates": "head 70e79e2d: dispatch-gates --commands derived 44; all 44 run, exit captured before any pipe, 44 x exit 0. --ran with recorded exit codes: 44 derived, 44 run, 0 NOT-MEASURED (derived zero). Named: check:doc-authoring 0, check:doc-anchors 0 (606 fragment links), check:role-word 0, spec check:skill-examples 0 (263 marked examples, was 262), spec check:docs 0. lychee (Check Documentation Links, advisory): NOT MEASURED locally (no binary), read from the PR check run. CI check-runs: in_progress at report time.",
      "line_budget": "+54 / -1 across 3 files (human-merge threshold 3000: under)",
      "files_changed": [
        "content/docs/permissions/access-recipes.mdx",
        "content/docs/permissions/administrator-guide.mdx",
        "content/docs/permissions/field-level-security.mdx"
      ],
      "deviations": [
        "First draft used the word 'role' (as the card does); check:role-word refused it (ADR-0090 D3), so the recipe title and links say 'position'. Recipe anchor is #data-lock-fields-for-a-position-once-a-record-reaches-a-stage.",
        "Worktree: the harness-pinned branch was checked out in the primary checkout, so the primary was detached and the worktree objectstack-issue-26178 was added on the same branch (no new branch).",
        "Editor path is written as Setup, Access Control, Permission Sets (the matrix editor where the When (edit) column lives, PermissionMatrixEditor.tsx); the card said 'Studio path'. Whether Studio's Access pillar opens the same editor was not measured, so the recipe does not claim it."
      ],
      "dogfood_battery": "n/a — no ! in the PR title and Clause-②: no without a narrowing arm",
      "mcp_calls": "4 — GitHub MCP reads only: issue_read get x1, issue_read get_comments x2, issue_read get_labels x1 (answered not found for the PR number); no MCP write",
      "api_writes": "2 REST-side strokes via the fleet-write relay: 1 repository_dispatch for pr_create (POST pulls, POST issues/26251/assignees, POST issues/26251/labels) and 1 for this report comment (POST issues/26178/comments). git push x2 is not a REST write.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    devx seat 2 · review: ACCEPT → PR #26251 (Fixes #26178) comment 6422246581 on head 70e79e2d8b. Every check is green or skipped. Not governed. Landing: ready + auto-merge.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdocumentationImprovements or additions to documentationdomain:devxDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions