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
connector credential borrowing follow-ups of #27746: an adopted plugin driver's boot-time failed-credentials verdict clears once the instance is repaired, and the connector path reuses borrowedCredentialForms — epic #27261 #27919
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Filing gate: ① should-fixes of the delta contract review of PR #27819 (record 6514494060, VERDICT PASS on 3351ae35), not taken into that PR.
Ruling-ref: 6486136301 (#27298, D7)
Dedupe (open AND closed): "failed-credentials adopted plugin driver borrowedCredentialForms credentialForms" → none this work.
Reader: the epic PM (#27261) dispatches it in the epic subtree.
Blocked-by: #27746
type: Bug
An adopted plugin driver's failed-credentials verdict and its unavailable mark clear on the next successful borrow (preferred), or the guard comment and the datasource banner say the verdict is the boot-time judgment, until restart. Pin the chosen behaviour.
packages/services/service-automation/src/connector-credentials.ts's credentialForms is replaced by borrowedCredentialForms from @objectstack/types, so the connector path also scrubs the form-encoded spelling. Pin it with a case that echoes a form-encoded credential in an upstream message.
Clause-②: decided by the dev from the diff · Metadata-protocol: none.
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Claim: PM loop round 14 2026-10-30T04:35Z
Session: session_017ihL2c5z3q4h8inrn5kwqV (epic PM); implementing card thread session_017ihL2eVFL4vpCbzypgy7JU
Account: marchtian
Branch: claude/project-thread-k4n62h (the card thread's platform-assigned branch — measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-27919
Domain: domain:server
Seat: epic:#27261#1 (epic PM; no domain:* seat). Filing gate ① (record 6514494060 should-fixes), D7 ruling 6486136301
File surface: packages/types/src/connector-credential-source.ts (an optional onLent(listener) on the lender contract), packages/services/service-datasource/src/** (the already-registered guard subscribes, and the next successful borrow re-records the datasource and clears the unavailable mark; degraded-boot banner text), packages/services/service-automation/src/connector-credentials.ts and connector-credential-source.ts (credentialForms delegates to borrowedCredentialForms; the provider emits onLent), their tests, .changeset/** (stop on breach, including any packages/spec/src/** edit; explain in the report)
Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: yes
Metadata-protocol: none
Responsibility: should-fixes of record 6514494060 on #27746 (PR #27819, ed8b2375)
Thread-read: none
Premise: holds — on origin/main (ed8b2375+), an adopted plugin driver's boot-time failed-credentials verdict and unavailable mark persist after the instance is repaired, until restart; connector-credentials.ts's credentialForms duplicates borrowedCredentialForms and omits the form-encoded spelling.
Serial constraints: #27875 (in flight) edits driver-odata/src/plugin.ts and serve.ts; neither is on this surface. A new member of a published @objectstack/types contract: the PR body says "Fable review owed" and lands after a contract review record PASS at the face's tier.
{
"issue": 27919,
"status": "done",
"branch": "claude/project-thread-k4n62h",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27990",
"head": "016e23cd",
"session": "session_017ihL2eVFL4vpCbzypgy7JU",
"premise_still_valid": true,
"summary": "Task 1 (preferred arm): IConnectorCredentialSource gains optional onLent(listener) in @objectstack/types; service-automation's source announces every granted borrow by instance name (never a refusal, listener throws isolated). DatasourceConnectionService: when the already-registered guard records failed-credentials for an adopted plugin driver, it subscribes once per lender and keeps {connector, reason}; a grant for THAT connector re-records already-registered (clears the engine's unavailable mark) only if the retained state is still that verdict and the driver is still registered. A grant for another instance leaves it. connect/reconnect/disconnect drop the entry, disconnectAll unsubscribes. No lender or no onLent: unchanged, banner keeps the restart text; with onLent the degraded-boot banner says the next granted borrow clears it (handleFailure gains an optional recovery sentence). Task 2: credentialForms keeps its signature and three callers and delegates to borrowedCredentialForms, so the form-encoded spelling is withheld on the connector path.",
"tests": "New: service-datasource 5 (real ObjectQL + DatasourceAdminServicePlugin retraction with other-instance grant not clearing; one subscription per lender released by disconnectAll; disconnect resurrects nothing; evicted driver keeps verdict; banner text both arms), service-automation 3 (onLent grant/refusal/unsubscribe; throwing listener; e2e api-key 401 echoing a form-encoded query string, no spelling in reason, listing or logs). Ablations red then restored: retractOnLend no-op; connector match removed; form-encoded spelling filtered. Suites: types 832, service-datasource 1069, service-automation 2824 (after merging main 9900366e), driver-odata 727, all pass. Typecheck exit 0 on the three packages, eslint clean on changed files.",
"gates": "dispatch-gates --commands derived 62 families on the merged head (same 62 before the merge); all run, exit codes recorded before any pipe; first pass check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads exit 3 (prerequisites), green after fetching the fixture commit and pnpm build. Final --ran: 62 derived, 62 run, 0 NOT-MEASURED (a DERIVED zero).",
"dogfood_battery": "n/a: no ! in the title, no (narrowing) arm",
"mcp_calls": "github issue_read x2 (#27919 get, get_comments), subscribe_pr_activity x1 (platform subscription); no MCP write tool",
"api_writes": "2: relay pr_create (run 41014459966, PR #27990, body 9498 bytes read back identical, assignee marchtian); relay comment on #27919 (this report). git push is not a REST write.",
"surface_note": "All edits inside the claim's file surface: packages/types/src/connector-credential-source.ts, packages/services/service-datasource/src (connection service + its connector-credential test), packages/services/service-automation/src (connector-credentials.ts, connector-credential-source.ts, their tests), one changeset. No packages/spec edit.",
"deviations": [
"credentialForms is kept as a two-line adapter over borrowedCredentialForms instead of being deleted: its callers hold a value plus an optional basic username, and the credential door's write has no auth to build a BorrowedConnectorAuth from. One list of spellings either way.",
"Clause-② written as 'yes (widening)' in the PR body and changeset (the claim says 'yes'); same declaration with its arm."
],
"open_questions": [],
"out_of_scope_findings": []
}
PR #27990 merged through the queue as 00c9a0b4 (head 016e23cd; contract review PASS 6516578586 at TIER_DEFAULT, the declaration face; seat ACCEPT followed). A plugin-driver datasource that boot recorded failed-credentials for its connector instance now recovers on the first borrow the lender grants for that instance, with no restart: IConnectorCredentialSource.onLent (optional) announces each grant, and the connection service retracts the verdict and the engine's unavailable mark. The connector call path's credentialForms now takes borrowedCredentialForms' list, so the form-encoded spelling is withheld too.
Activity
objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Claim: PM loop round 14 2026-10-30T04:35Z
Session:
session_017ihL2c5z3q4h8inrn5kwqV(epic PM); implementing card threadsession_017ihL2eVFL4vpCbzypgy7JUAccount:
marchtianBranch:
claude/project-thread-k4n62h(the card thread's platform-assigned branch — measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-27919Domain:
domain:serverSeat:
epic:#27261#1(epic PM; nodomain:*seat). Filing gate ① (record 6514494060 should-fixes), D7 ruling 6486136301File surface:
packages/types/src/connector-credential-source.ts(an optionalonLent(listener)on the lender contract),packages/services/service-datasource/src/**(the already-registered guard subscribes, and the next successful borrow re-records the datasource and clears the unavailable mark; degraded-boot banner text),packages/services/service-automation/src/connector-credentials.tsandconnector-credential-source.ts(credentialFormsdelegates toborrowedCredentialForms; the provider emitsonLent), their tests,.changeset/**(stop on breach, including anypackages/spec/src/**edit; explain in the report)Container & model:
S,mode:thread,model: default tier (dispatch-gates --tier: no path-derived mandate),effort: highClause-②: yes
Metadata-protocol: none
Responsibility: should-fixes of record 6514494060 on #27746 (PR #27819,
ed8b2375)Thread-read: none
Premise: holds — on
origin/main(ed8b2375+), an adopted plugin driver's boot-timefailed-credentialsverdict and unavailable mark persist after the instance is repaired, until restart;connector-credentials.ts'scredentialFormsduplicatesborrowedCredentialFormsand omits the form-encoded spelling.Serial constraints: #27875 (in flight) edits
driver-odata/src/plugin.tsandserve.ts; neither is on this surface. A new member of a published@objectstack/typescontract: the PR body says "Fable review owed" and lands after a contract review record PASS at the face's tier.objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2eVFL4vpCbzypgy7JU
os-dev-report
{ "issue": 27919, "status": "done", "branch": "claude/project-thread-k4n62h", "pr": "https://github.com/objectstack-ai/objectstack/pull/27990", "head": "016e23cd", "session": "session_017ihL2eVFL4vpCbzypgy7JU", "premise_still_valid": true, "summary": "Task 1 (preferred arm): IConnectorCredentialSource gains optional onLent(listener) in @objectstack/types; service-automation's source announces every granted borrow by instance name (never a refusal, listener throws isolated). DatasourceConnectionService: when the already-registered guard records failed-credentials for an adopted plugin driver, it subscribes once per lender and keeps {connector, reason}; a grant for THAT connector re-records already-registered (clears the engine's unavailable mark) only if the retained state is still that verdict and the driver is still registered. A grant for another instance leaves it. connect/reconnect/disconnect drop the entry, disconnectAll unsubscribes. No lender or no onLent: unchanged, banner keeps the restart text; with onLent the degraded-boot banner says the next granted borrow clears it (handleFailure gains an optional recovery sentence). Task 2: credentialForms keeps its signature and three callers and delegates to borrowedCredentialForms, so the form-encoded spelling is withheld on the connector path.", "tests": "New: service-datasource 5 (real ObjectQL + DatasourceAdminServicePlugin retraction with other-instance grant not clearing; one subscription per lender released by disconnectAll; disconnect resurrects nothing; evicted driver keeps verdict; banner text both arms), service-automation 3 (onLent grant/refusal/unsubscribe; throwing listener; e2e api-key 401 echoing a form-encoded query string, no spelling in reason, listing or logs). Ablations red then restored: retractOnLend no-op; connector match removed; form-encoded spelling filtered. Suites: types 832, service-datasource 1069, service-automation 2824 (after merging main 9900366e), driver-odata 727, all pass. Typecheck exit 0 on the three packages, eslint clean on changed files.", "gates": "dispatch-gates --commands derived 62 families on the merged head (same 62 before the merge); all run, exit codes recorded before any pipe; first pass check-plugin-teardown-shape --self-test and check:dual-build-cjs-loads exit 3 (prerequisites), green after fetching the fixture commit and pnpm build. Final --ran: 62 derived, 62 run, 0 NOT-MEASURED (a DERIVED zero).", "dogfood_battery": "n/a: no ! in the title, no (narrowing) arm", "mcp_calls": "github issue_read x2 (#27919 get, get_comments), subscribe_pr_activity x1 (platform subscription); no MCP write tool", "api_writes": "2: relay pr_create (run 41014459966, PR #27990, body 9498 bytes read back identical, assignee marchtian); relay comment on #27919 (this report). git push is not a REST write.", "surface_note": "All edits inside the claim's file surface: packages/types/src/connector-credential-source.ts, packages/services/service-datasource/src (connection service + its connector-credential test), packages/services/service-automation/src (connector-credentials.ts, connector-credential-source.ts, their tests), one changeset. No packages/spec edit.", "deviations": [ "credentialForms is kept as a two-line adapter over borrowedCredentialForms instead of being deleted: its callers hold a value plus an optional basic username, and the credential door's write has no auth to build a BorrowedConnectorAuth from. One list of spellings either way.", "Clause-② written as 'yes (widening)' in the PR body and changeset (the claim says 'yes'); same declaration with its arm." ], "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Landed · 2026-10-30T07:36Z
PR #27990 merged through the queue as
00c9a0b4(head016e23cd; contract review PASS 6516578586 atTIER_DEFAULT, the declaration face; seat ACCEPT followed). A plugin-driver datasource that boot recordedfailed-credentialsfor its connector instance now recovers on the first borrow the lender grants for that instance, with no restart:IConnectorCredentialSource.onLent(optional) announces each grant, and the connection service retracts the verdict and the engine's unavailable mark. The connector call path'scredentialFormsnow takesborrowedCredentialForms' list, so the form-encoded spelling is withheld too.