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
datasources: POST /datasources/NAME/external/validate answers an unknown name 200 with an empty report, where every other by-name datasource door answers 404 RESOURCE_NOT_FOUND #27696
Found by the #27618 card thread (os-dev-report on #27618, out_of_scope_findings, read from the code, not measured). Same family as #27510 / #27618: by-name doors disagree on an unknown name.
What is wrong
PR #27693 (#27618) makes the federation guard answer a name that no saved datasource has 404 RESOURCE_NOT_FOUND on the Sync doors and their /external/ twins (tables, tables/:remote/draft, tables/:remote/import, refresh-catalog), as GET /api/v1/datasources/:name does. POST /api/v1/datasources/:name/external/validate (packages/rest/src/external-datasource-routes.ts, validateDatasource(:name)) does not run that guard: for a name that resolves no saved datasource it answers 200 with an empty report (ok: true, no results). A caller cannot tell "this datasource has nothing to validate" from "this datasource does not exist".
Re-check after #27693 merges: POST /api/v1/datasources/nope/external/validate as an admin, and compare with GET /api/v1/datasources/nope.
Expected
The validate door answers an unknown name 404 RESOURCE_NOT_FOUND through the package's one datasourceNotFoundError, before any validation, like its by-name siblings. A datasource that exists and has nothing federated keeps its 200 empty report. A narrowing (200 → 404): Clause-②: no (narrowing), contract review before approval.
Claim: PM loop round 2 · 2026-10-30T02:37Z
Session: session_016WV4cx56cEs32AZSfABRR8 (card thread; seat session_016WV4czuTWNgKR22fKv7jia)
Account: os-elon-musk
Branch: claude/project-thread-rsztyz (the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)
Worktree: objectstack-issue-27696
Domain: domain:server
Seat: domain:server#3
File surface: packages/services/service-datasource/src/external-datasource-service.ts (validateDatasource's existence check, the one testConnection runs, #27510) and its tests, packages/rest/src/external-datasource-routes.ts (comments and tests only), .changeset/* (amended by the seat on the thread's measured need: the route already relays the 404, and the empty report comes from the service)
Container & model: S, mode:thread, model: opus (TIER_DEFAULT; a CONTRACT_REVIEW_TIER review is owed before the queue: triage grades it a narrowing), effort: medium
Clause-②: no (narrowing), per triage
Metadata-protocol: none
Responsibility: POST /api/v1/datasources/:name/external/validate on a name no saved datasource has.
Thread-read: 6506948888
Premise: holds (code read; the dev re-measures on main with #27693)
Serial constraints cleared: unblocked: the wait was on PR #27693, merged. Re-derived: no open PR touches external-datasource-routes.ts or external-datasource-service.ts at amendment time.
{
"issue": 27696,
"status": "done",
"branch": "claude/project-thread-rsztyz",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27911",
"session": "session_016WV4cx56cEs32AZSfABRR8",
"premise_still_valid": true,
"summary": "POST /api/v1/datasources/NAME/external/validate answered an unknown name 200 with an empty ok report (measured red on main da94c113). ExternalDatasourceService.validateDatasource now checks existence first, the check testConnection makes (#27510): the primary datasource is not looked up, any other name with no saved record throws the package's one datasourceNotFoundError before listObjects or introspection; the route already relays that envelope as 404 since #27618, so it only gains a comment. Existence only, not assertFederationSource: a saved datasource with nothing federated (managed included) and the primary one keep the 200 empty report. Claim surface amended by the seat before push to add external-datasource-service.ts and its test.",
"tests": "New pins: rest external-datasource-unknown-name.test.ts (unknown name 404 RESOURCE_NOT_FOUND in GET's words; warehouse and default keep 200 {ok:true,results:[]}), service external-datasource-service.test.ts (rejects with status 404 / RESOURCE_NOT_FOUND / datasourceNotFoundError message, listObjects never called, nothing introspected; a saved datasource nothing is bound to keeps the empty report). Updated: rest external-datasource-validate-scope.test.ts unknown-name cell flipped from the old 200 to the ruled 404. Red on main: rest validate cell 'expected { status: 200, success: true } to deeply equal { status: 404, success: false }'. Ablation (check removed, restored): service 1 failed/43, rest 1 failed/15; restored 43/43, 15/15. Suites: rest Test Files 352/352, Tests 7023 passed 350 skipped; service-datasource 63/63 files, 1029 tests; runtime external-validation* 4 files 44 tests; tsc --noEmit rest 0, service-datasource 0.",
"gates": "At bdbdaae5: dispatch-gates --commands derived 62 families; 61 exit 0; pnpm check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, whole-tree dist) = NOT MEASURED locally, CI runs it. --ran: 62 derived, 61 run, 1 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check-commit-card-trailers --range origin/main..HEAD exit 0. CI check-runs: in_progress at report time.",
"dogfood_battery": "bdbdaae5 · os-verify-lock: VERDICT command-exit 1 · Test Files 353 passed / 3 failed / 3 skipped (359) · Tests 2867 passed / 4 failed / 20 skipped (2891). All 4 failures are main-side, none touch datasources: error-sentences-live.dogfood.test.ts acceptance[1] x2 and object-hook-lifecycle-scratch.dogfood.test.ts acceptance[6] = the HOOK_ABORTED pins of #27806 (fixed on main by #27878 after this branch's base); platform-app-object-entry-views.test.ts 'named objects neither source declares: [sys_exchange_rate]' = from #27246 (sys_exchange_rate), in the #27813 4-hourly red range. Named, not fixed.",
"mcp_calls": "4 — mcp__github__issue_read x4 (#27696 get, #27696 comments, #27806, #27813); no MCP write",
"api_writes": "3 — git push (branch); relay pr_create (#27911, read-back identical 5949 bytes); relay comment (this os-dev-report on #27696)",
"deviations": ["Ablation ran on the source with a python str.replace and a backup restore, before the commit, not via scripts/ablation-replace.mjs; landing evidenced by the diff stat moving (21 -> 18 lines) and the two pins turning red, restore by both pins green again. No dist was in the path (both suites resolve service-datasource to src/).", "File surface wider than the dispatch order (service file + test), amended by the seat on claim 6513584871 before push."],
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 可对外的 API | integration-system.datasource-admin-lifecycle | P②
Triage: p2 ·
domain:server·area:api·pm:blockedon PR #27693 · 2026-10-29T19:58Z⛔ Not a claim.
datasourceNotFoundError. An existing datasource with nothing federated keeps its 200 empty report.Clause-②: no (narrowing)and a contract review.bug,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-30T02:37Z
Session:
session_016WV4cx56cEs32AZSfABRR8(card thread; seatsession_016WV4czuTWNgKR22fKv7jia)Account:
os-elon-muskBranch:
claude/project-thread-rsztyz(the card thread's platform-assigned branch — the recorded platform exception; amended by the seat when the thread reported it)Worktree:
objectstack-issue-27696Domain:
domain:serverSeat:
domain:server#3File surface:
packages/services/service-datasource/src/external-datasource-service.ts(validateDatasource's existence check, the onetestConnectionruns, #27510) and its tests,packages/rest/src/external-datasource-routes.ts(comments and tests only),.changeset/*(amended by the seat on the thread's measured need: the route already relays the 404, and the empty report comes from the service)Container & model:
S,mode:thread,model: opus (TIER_DEFAULT; a CONTRACT_REVIEW_TIER review is owed before the queue: triage grades it a narrowing),effort: mediumClause-②: no (narrowing), per triage
Metadata-protocol: none
Responsibility:
POST /api/v1/datasources/:name/external/validateon a name no saved datasource has.Thread-read: 6506948888
Premise: holds (code read; the dev re-measures on
mainwith #27693)Serial constraints cleared: unblocked: the wait was on PR #27693, merged. Re-derived: no open PR touches
external-datasource-routes.tsorexternal-datasource-service.tsat amendment time.objectstack-fleet commentedon Oct 30, 2026
os-dev-report
{ "issue": 27696, "status": "done", "branch": "claude/project-thread-rsztyz", "pr": "https://github.com/objectstack-ai/objectstack/pull/27911", "session": "session_016WV4cx56cEs32AZSfABRR8", "premise_still_valid": true, "summary": "POST /api/v1/datasources/NAME/external/validate answered an unknown name 200 with an empty ok report (measured red on main da94c113). ExternalDatasourceService.validateDatasource now checks existence first, the check testConnection makes (#27510): the primary datasource is not looked up, any other name with no saved record throws the package's one datasourceNotFoundError before listObjects or introspection; the route already relays that envelope as 404 since #27618, so it only gains a comment. Existence only, not assertFederationSource: a saved datasource with nothing federated (managed included) and the primary one keep the 200 empty report. Claim surface amended by the seat before push to add external-datasource-service.ts and its test.", "tests": "New pins: rest external-datasource-unknown-name.test.ts (unknown name 404 RESOURCE_NOT_FOUND in GET's words; warehouse and default keep 200 {ok:true,results:[]}), service external-datasource-service.test.ts (rejects with status 404 / RESOURCE_NOT_FOUND / datasourceNotFoundError message, listObjects never called, nothing introspected; a saved datasource nothing is bound to keeps the empty report). Updated: rest external-datasource-validate-scope.test.ts unknown-name cell flipped from the old 200 to the ruled 404. Red on main: rest validate cell 'expected { status: 200, success: true } to deeply equal { status: 404, success: false }'. Ablation (check removed, restored): service 1 failed/43, rest 1 failed/15; restored 43/43, 15/15. Suites: rest Test Files 352/352, Tests 7023 passed 350 skipped; service-datasource 63/63 files, 1029 tests; runtime external-validation* 4 files 44 tests; tsc --noEmit rest 0, service-datasource 0.", "gates": "At bdbdaae5: dispatch-gates --commands derived 62 families; 61 exit 0; pnpm check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, whole-tree dist) = NOT MEASURED locally, CI runs it. --ran: 62 derived, 61 run, 1 NOT-MEASURED, 0 UNRUN. pnpm lint exit 0. check-commit-card-trailers --range origin/main..HEAD exit 0. CI check-runs: in_progress at report time.", "dogfood_battery": "bdbdaae5 · os-verify-lock: VERDICT command-exit 1 · Test Files 353 passed / 3 failed / 3 skipped (359) · Tests 2867 passed / 4 failed / 20 skipped (2891). All 4 failures are main-side, none touch datasources: error-sentences-live.dogfood.test.ts acceptance[1] x2 and object-hook-lifecycle-scratch.dogfood.test.ts acceptance[6] = the HOOK_ABORTED pins of #27806 (fixed on main by #27878 after this branch's base); platform-app-object-entry-views.test.ts 'named objects neither source declares: [sys_exchange_rate]' = from #27246 (sys_exchange_rate), in the #27813 4-hourly red range. Named, not fixed.", "mcp_calls": "4 — mcp__github__issue_read x4 (#27696 get, #27696 comments, #27806, #27813); no MCP write", "api_writes": "3 — git push (branch); relay pr_create (#27911, read-back identical 5949 bytes); relay comment (this os-dev-report on #27696)", "deviations": ["Ablation ran on the source with a python str.replace and a backup restore, before the commit, not via scripts/ablation-replace.mjs; landing evidenced by the diff stat moving (21 -> 18 lines) and the two pins turning red, restore by both pins green again. No dist was in the path (both suites resolve service-datasource to src/).", "File surface wider than the dispatch order (service file + test), amended by the seat on claim 6513584871 before push."], "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
objectstack-fleet commentedon Oct 30, 2026
domain:server#3 · os-elon-musk · session_016WV4czuTWNgKR22fKv7jia
ACCEPT → PR #27911 comment 6514574747 · 2026-10-30T03:57Z · ready + auto-merge armed through the relay.