You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rest: POST /data/:object/import (synchronous import) on an unregistered object answers 200 with a per-row OBJECT_NOT_FOUND, where POST /data/:object answers 404 #27728
Found by the dev of #27501 ask (a), PR #27711 (os-dev-report 6508232970, out-of-scope finding). Out of that card's scope: triage 6498786930 named only the async job door.
What is wrong
The synchronous import door POST /data/:object/import (packages/rest/src/data-action-routes.ts, the route registered at ${dataPath}/:object/import) runs no existence check on :object. For a name with no object behind it, it answers 200 and reports OBJECT_NOT_FOUND inside each row's result. POST /data/:object for the same name answers 404 OBJECT_NOT_FOUND. An automated importer that reads the status sees success for a misspelled object name.
#27501's reproduction step 3 measured this on main before #27711. #27711 closes the same gap on the async door POST /data/:object/import/jobs with assertImportObjectExists, called right after the API-exposure gate.
Expected
The synchronous door refuses an unregistered object with the data door's answer (404 OBJECT_NOT_FOUND, same envelope), before any row is written, with the same read and the same posture as #27711 (after the exposure gate, so it is no existence oracle). Refusing what used to answer 200 is a narrowing; triage decides Clause-②.
Re-check after #27711 merges: a JSON import to POST /api/v1/data/<unregistered name>/import; read the status and code.
Claim: PM loop round 2 · 2026-10-30T01:49Z
Session: session_016WV4cxENxbA8ZpRgwafjvs (card thread; seat session_016WV4czuTWNgKR22fKv7jia)
Account: os-elon-musk
Branch: claude/project-thread-trba3v (the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)
Worktree: objectstack-issue-27728
Domain: domain:server
Seat: domain:server#3
File surface: packages/rest/src/data-action-routes.ts (the synchronous import door), tests, .changeset/*; carried with #27729 in one thread
Container & model: M (with #27729), mode:thread, model: opus (TIER_DEFAULT; a CONTRACT_REVIEW_TIER review is owed before the queue: triage grades it a narrowing), effort: high
Clause-②: no (narrowing), per triage
Metadata-protocol: none
Responsibility: POST /api/v1/data/:object/import (synchronous import) on an unregistered object.
Thread-read: 6509235875
Premise: holds (re-measured by the dev on main with #27711)
Serial constraints cleared: unblocked: the wait was on PR #27711, merged. Re-derived: PR #27795 (#27676, in the queue) edits the async import region of the same file; the later lander merges main.
{
"issue": 27728,
"status": "done",
"branch": "claude/project-thread-trba3v",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27897",
"session": "session_016WV4cxENxbA8ZpRgwafjvs",
"premise_still_valid": true,
"summary": "#27728: POST /data/:object/import calls assertImportObjectExists after the exposure gate and before the body parse; an unregistered object answers the data door's 404 OBJECT_NOT_FOUND (body equal), a disabled package's object its 404 OBJECT_PACKAGE_DISABLED. #27729: the job door's disabled-package refusal is pinned (status+body equal, zero job rows); assertImportObjectExists and the exposure gate's loadObjectItem drop item.name === name, so a legacy ns__short short name is the object registry.getObject resolves at every door. Measured on the base: an apiEnabled:false ns__short object was served under its short name (data door 201, sync import 200); now 404 OBJECT_API_DISABLED at all three doors. Carries #27729 in the same PR.",
"tests": "new packages/rest/src/import-door-object-existence.test.ts 11/11 (real ObjectQL + protocol + sqlite :memory:). Ablation: both source files reverted to main, test kept -> 6/11 red (2 #27728 cases, sync disabled-package, 3 short-name cases); restored 11/11. rest package: Test Files 353 passed (353), Tests 7031 passed, 350 skipped. rest is tested from src (the subject is not resolved through dist), so no dist ablation leg applies.",
"gates": "dispatch-gates --commands: 60 derived; 59 exit 0; NOT MEASURED: pnpm check:dual-build-cjs-loads (exit 3, needs every package's dist). check-plugin-teardown-shape --self-test exit 3 in the shallow clone, 0 after fetching its pinned commit. --ran: 60 accounted, 59 run, 1 NOT-MEASURED. Outside the derivation: pnpm lint exit 0; pnpm --filter @objectstack/rest run typecheck exit 0. CI check-runs: pending at report time.",
"dogfood_battery": "c0b19922 · os-verify-lock: VERDICT command-exit 1 · Test Files 353/359 passed (3 failed, 3 skipped) · Tests 2867/2891 passed (4 failed, 20 skipped) · failures, all main-side: error-sentences-live acceptance[1] POST /data/OBJECT and /createMany, object-hook-lifecycle-scratch acceptance[6] negative[0] (#27806, HOOK_ABORTED); platform-app-object-entry-views 'every object an entry names is declared...' expected ['sys_exchange_rate'] (#27813 red 2, from 194e66c0)",
"line_budget": "4 files, +276/-21 (297 lines, under 3000): data-action-routes.ts, meta-item-read-gate.ts, new test, changeset",
"files_changed": [
".changeset/27728-27729-import-doors-object-existence.md",
"packages/rest/src/data-action-routes.ts",
"packages/rest/src/meta-item-read-gate.ts",
"packages/rest/src/import-door-object-existence.test.ts"
],
"deviations": [
"The exposure gate edit lives in meta-item-read-gate.ts (packages/rest/src/**, inside the file surface) per triage 6509225810 'the exposure gate reads the same way'.",
"No local test:repo run (CI's Test Core)."
],
"mcp_calls": "9 — read only: issue_read x5, search_issues x1, subscribe_pr_activity x1 (platform PR watch), plus 2 ToolSearch loads; zero MCP writes",
"api_writes": "2 — relay pr_create (#27897), relay comment (this report)",
"open_questions": [],
"out_of_scope_findings": [
"class: c · reach: POST /batch per-op exposure gate (batch-routes.ts) keys the object list by name, so an ns__short object's enable is not judged under its short name · evidence: read from the code, not measured (this harness answers 501 for a transactional batch) · dedupe words: batch exposure gate short name ns__short apiEnabled",
"carrier: PR #27897 Acceptance notes · noted, not filed"
]
}
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 可对外的 API | none | P②
Triage: p2 ·
domain:server·area:api·pm:blockedon PR #27711 · 2026-10-29T21:55Z⛔ Not a claim.
OBJECT_NOT_FOUNDbefore any row, placed after the exposure gate (no existence oracle), with the same read as fix(rest)!: an async import job for an unregistered object is refused with 404 OBJECT_NOT_FOUND before any job is created #27711 and rest: pin the async import job door's disabled-package refusal, and decide whether it should resolve a legacyns__shortname as the data door does #27729.Clause-②: no (narrowing)and a contract review.pm:blocked.Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia
Claim: PM loop round 2 · 2026-10-30T01:49Z
Session:
session_016WV4cxENxbA8ZpRgwafjvs(card thread; seatsession_016WV4czuTWNgKR22fKv7jia)Account:
os-elon-muskBranch:
claude/project-thread-trba3v(the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)Worktree:
objectstack-issue-27728Domain:
domain:serverSeat:
domain:server#3File surface:
packages/rest/src/data-action-routes.ts(the synchronous import door), tests,.changeset/*; carried with #27729 in one threadContainer & model:
M(with #27729),mode:thread,model: opus (TIER_DEFAULT; a CONTRACT_REVIEW_TIER review is owed before the queue: triage grades it a narrowing),effort: highClause-②: no (narrowing), per triage
Metadata-protocol: none
Responsibility:
POST /api/v1/data/:object/import(synchronous import) on an unregistered object.Thread-read: 6509235875
Premise: holds (re-measured by the dev on
mainwith #27711)Serial constraints cleared: unblocked: the wait was on PR #27711, merged. Re-derived: PR #27795 (#27676, in the queue) edits the async import region of the same file; the later lander merges
main.objectstack-fleet commentedon Oct 30, 2026
domain:server#3 · os-elon-musk · session_016WV4cxENxbA8ZpRgwafjvs
os-dev-report · #27728 + #27729 · PR #27897 · head c0b1992
{ "issue": 27728, "status": "done", "branch": "claude/project-thread-trba3v", "pr": "https://github.com/objectstack-ai/objectstack/pull/27897", "session": "session_016WV4cxENxbA8ZpRgwafjvs", "premise_still_valid": true, "summary": "#27728: POST /data/:object/import calls assertImportObjectExists after the exposure gate and before the body parse; an unregistered object answers the data door's 404 OBJECT_NOT_FOUND (body equal), a disabled package's object its 404 OBJECT_PACKAGE_DISABLED. #27729: the job door's disabled-package refusal is pinned (status+body equal, zero job rows); assertImportObjectExists and the exposure gate's loadObjectItem drop item.name === name, so a legacy ns__short short name is the object registry.getObject resolves at every door. Measured on the base: an apiEnabled:false ns__short object was served under its short name (data door 201, sync import 200); now 404 OBJECT_API_DISABLED at all three doors. Carries #27729 in the same PR.", "tests": "new packages/rest/src/import-door-object-existence.test.ts 11/11 (real ObjectQL + protocol + sqlite :memory:). Ablation: both source files reverted to main, test kept -> 6/11 red (2 #27728 cases, sync disabled-package, 3 short-name cases); restored 11/11. rest package: Test Files 353 passed (353), Tests 7031 passed, 350 skipped. rest is tested from src (the subject is not resolved through dist), so no dist ablation leg applies.", "gates": "dispatch-gates --commands: 60 derived; 59 exit 0; NOT MEASURED: pnpm check:dual-build-cjs-loads (exit 3, needs every package's dist). check-plugin-teardown-shape --self-test exit 3 in the shallow clone, 0 after fetching its pinned commit. --ran: 60 accounted, 59 run, 1 NOT-MEASURED. Outside the derivation: pnpm lint exit 0; pnpm --filter @objectstack/rest run typecheck exit 0. CI check-runs: pending at report time.", "dogfood_battery": "c0b19922 · os-verify-lock: VERDICT command-exit 1 · Test Files 353/359 passed (3 failed, 3 skipped) · Tests 2867/2891 passed (4 failed, 20 skipped) · failures, all main-side: error-sentences-live acceptance[1] POST /data/OBJECT and /createMany, object-hook-lifecycle-scratch acceptance[6] negative[0] (#27806, HOOK_ABORTED); platform-app-object-entry-views 'every object an entry names is declared...' expected ['sys_exchange_rate'] (#27813 red 2, from 194e66c0)", "line_budget": "4 files, +276/-21 (297 lines, under 3000): data-action-routes.ts, meta-item-read-gate.ts, new test, changeset", "files_changed": [ ".changeset/27728-27729-import-doors-object-existence.md", "packages/rest/src/data-action-routes.ts", "packages/rest/src/meta-item-read-gate.ts", "packages/rest/src/import-door-object-existence.test.ts" ], "deviations": [ "The exposure gate edit lives in meta-item-read-gate.ts (packages/rest/src/**, inside the file surface) per triage 6509225810 'the exposure gate reads the same way'.", "No local test:repo run (CI's Test Core)." ], "mcp_calls": "9 — read only: issue_read x5, search_issues x1, subscribe_pr_activity x1 (platform PR watch), plus 2 ToolSearch loads; zero MCP writes", "api_writes": "2 — relay pr_create (#27897), relay comment (this report)", "open_questions": [], "out_of_scope_findings": [ "class: c · reach: POST /batch per-op exposure gate (batch-routes.ts) keys the object list by name, so an ns__short object's enable is not judged under its short name · evidence: read from the code, not measured (this harness answers 501 for a transactional batch) · dedupe words: batch exposure gate short name ns__short apiEnabled", "carrier: PR #27897 Acceptance notes · noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia
ACCEPT → PR #27897 comment 6514232261 · 2026-10-30T03:28Z · contract review PASS 6513915701 + delta 6513977097 · ready + auto-merge armed through the relay.