Repository navigation
Description
Filing gate: ① user-visible defect in the shipped console (@objectstack/console@18.2.0), reproduced at a public door, with a named location.
- Business reason: the first thing a new user does after
npm create objectstackis open a record in the Console. The blank scaffold composes no approvals service, so every record page they open prints two red errors in the browser console for an answer the console itself treats as expected. A developer debugging their own app reads it as a broken server. It is the noise objectui#4042 set out to remove ("HTTP request failed" lines for requests that were never going to succeed). - Who acts: the seat owning ui/packages/app-shell (src/hooks/useRecordApprovals.ts, the readLock path) and the @objectstack/client logger it reads through. Possible fixes: skip the lock read when the requests read already showed no approvals service, read the lock with the hook's own fetchJson, which does not log, or have the client not log a 501 the caller declares expected. Alternatively the server side makes the two approvals doors agree (see below).
- Dedupe (open and closed): "console record page approvals lock 501 NOT_IMPLEMENTED console error without approvals service" gave 50 hits (top 10 read), and "console HTTP request failed 501 Not Implemented console error approvals service not configured" gave 6. None reports this. console: a non-participant reader is offered inline edit on a record whose pending approval locks it (lockRecord: true), and the save answers 409 RECORD_LOCKED #25934 and plugin-approvals: a record-anchored lock read,
{ locked: boolean }for every reader of the record, so a non-participant is not offered an edit the server refuses (#25934 ruling A) #26314 (closed) introduced the lock read.
reach: the Console on a fresh 18.2.0 scaffold (npm create objectstack@18.2.0), measured on 3 loads plus a second scaffold.
QA-source: #26629 · smoke:npm-18.2.0 · F5
type: Bug
Reproduction (published 18.2.0)
- npm create objectstack@18.2.0 my-app; cd my-app; npx os dev -p PORT (SQLite; the scaffold composes no approvals service).
- Sign in at /_console/ as the seeded dev admin, open /_console/apps/com.objectstack.setup/my_app_note, click New and save. Or open an existing note's panel with ?recordId=ID.
- The browser console shows, on every open:
- Failed to load resource: the server responded with a status of 501 (Not Implemented)
- HTTP request failed: GET /api/v1/approvals/records/my_app_note/ID/lock -> 501 [NOT_IMPLEMENTED]
- Server side: GET /api/v1/approvals/requests?object=my_app_note&recordId=ID answers 200 {"data":[]}, and GET /api/v1/approvals/records/my_app_note/ID/lock answers 501 {"code":"NOT_IMPLEMENTED","message":"Approvals service is not configured on this deployment"}.
Expected: no console error. useRecordApprovals.ts (27f38ad) documents the 501 as the designed answer of "a composition without the approvals service" and treats it as "not locked". Actual: two error-level lines per record open. The record itself saves and reads back fine.
Because the requests door answers 200, the hook takes the service to be present and goes on to the lock read. The two doors disagree on whether the service exists.
Full evidence chain: the run record #26629, cell F5.
Activity
objectstack-fleet commentedon Oct 27, 2026
Triage: first grade —
bug·priority:p2·domain:ui·area:workflow·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-27T12:00Z⛔ Not a claim, ⛔ not a dispatch.
{ locked: boolean }for every reader of the record, so a non-participant is not offered an edit the server refuses (#25934 ruling A) #26314). The record page treats a 501 from that read as "no lock service": silent, no retry. Any other failure still logs.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
Claim: PM loop round 1
Session:
session_01J8VVAkHqAv2eFKVSt9LqkCAccount:
huangyiireneBranch:
claude/project-thread-yltrjtWorktree:
objectstack-issue-26632Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/packages/app-shell/src/hooks/useRecordApprovals.tsand its tests (stop on breach; explain in the report)Container & model:
M,mode:thread,model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
the record page lock read logs the designed 501 through the client logger|the hook already fails open on 501; the log is the defect|every new user opening a record on a scaffold without the approvals serviceThread-read: 6441358448
Premise: holds
Serial constraints cleared: none open; last change on the file #26666 (a71564f) is merged
Dispatched to a card thread of the "objectstack ui" project (
mode:thread); the dispatch order is the thread's opening message. The platform names the thread branch (claude/project-thread-yltrjt), notclaude/issue-26632-approvals-lock-501. Read at 2026-10-27T13:04Z onorigin/mainf6ffd72347.Generated by Claude Code
objectstack-fleet commentedon Oct 27, 2026
os-dev-report
{ "issue": 26632, "status": "done", "branch": "claude/project-thread-yltrjt", "pr": "https://github.com/objectstack-ai/objectstack/pull/26841", "session": "session_01J8VVAojjEQUUoMeSBSdgW4", "premise_still_valid": true, "head": "a0185cfb", "summary": "Measured producer: @objectstack/client fetch() logs every non-2xx via logger.error, and the console's createQuietHttpLogger (ui/packages/data-objectstack) prints it with console.error before the hook's fail-open catch runs; PM hypothesis held. Landing in the expected file surface: useRecordApprovals reads the lock through its own fetchJson (the transport the approvals list read already uses), latches a 501 in a module flag so no record asks again until reload, and logs every other failure through the same createQuietHttpLogger. The adapter gate on the lock read is kept (dropping it surfaced a wave-2 lock read in RecordDetailView.recordOpenWaves-13010). @objectstack/client is not changed. Card assignee not touched.", "tests": "head a0185cfb: cd ui && pnpm exec vitest run packages/app-shell/src/hooks/useRecordApprovals packages/app-shell/src/hooks/__tests__/useRecordApprovals packages/app-shell/src/views/RecordDetailView.recordOpenWaves-13010.test.tsx packages/app-shell/src/views/RecordDetailView.approvalLock packages/app-shell/src/views/RecordApprovalsPanel -> Test Files 15 passed (15), Tests 107 passed (107), lock VERDICT command-exit 0. pnpm --filter @object-ui/app-shell run type-check -> exit 0. Ablation (scripts/ablation-replace.mjs, anchor 'if (err?.status === 501) {' -> 999501, no build needed: app-shell's own suite reads src): the new 501 test went red (1 failed | 5 passed) on the 'HTTP request failed: ... /lock -> 501 [NOT_IMPLEMENTED]' line; restore blob == HEAD 975d85f2a294, git diff HEAD empty. Narrowed, declared: the full app-shell package run was stopped after ~40 min on the shared box (it found the waves-13010 regression, since fixed); CI Test UI owns the full run.", "gates": "dispatch-gates --commands: 34 derived; all 34 run locally, each exit 0 (type-check-debt re-run under the verify lock after a first queue-timeout exit 3 = NOT MEASURED, then exit 0: 126/129 type-checked, 0 DEBT). dispatch-gates --ran on the first record: 33 run, 1 UNRUN (type-check-debt), since run. node scripts/check-sdui-manifest.mjs exit 0. CI check-runs: in_progress at report time (seat owns convergence).", "line_budget": "218 changed lines (+167/-51), 3 files; under the 3000 human-merge threshold", "files_changed": [ ".changeset/26632-record-lock-501-silent.md", "ui/packages/app-shell/src/hooks/useRecordApprovals.ts", "ui/packages/app-shell/src/views/RecordDetailView.approvalLock-25934.test.tsx" ], "deviations": [ "Branch is the platform-named claude/project-thread-yltrjt, not claude/issue-26632-*, as the Claim records; worked in the container's own clone on that branch, not a git worktree.", "Lock test lives in views/RecordDetailView.approvalLock-25934.test.tsx (the hook's existing lock test), rewritten from the adapter SDK stub to the global fetch stub.", "Lock read no longer carries the SDK client's X-Environment-Id / Accept-Language headers; the sibling approvals list read never did, and the console adapter sets no environment id.", "Harness commit-attribution reminder named a model in Co-Authored-By; commits use the AGENTS.md model-free trailer pair instead." ], "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "mcp_calls": "2 — mcp__github__issue_read (get, get_comments); no write tool", "api_writes": "2 — relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + POST /issues/26841/assignees, run 40558873139), relay comment (this report)", "open_questions": [], "out_of_scope_findings": [ "class: none (not filed) · the approvals list door answers 200 {data: []} without the service while the lock door answers 501 (packages/rest/src/approvals-routes.ts), so the browser's own network line for the first 501 still appears once per page load; making the doors agree is domain:server · carrier: #26632 (named in its body as the alternative) · noted in PR Acceptance notes, not filed" ] }Generated by Claude Code