-
Notifications
You must be signed in to change notification settings - Fork 3
plat 267
| Coordination | Value |
|---|---|
| Assigned agent | Claude Code |
| Ticket state | fixed, live-verified on the Dominion deployment |
| Last synchronized | 2026-09-01 |
-
Priority: secrets/authorization, severity high — every scheduled run
of an affected workflow silently loses access to all of its own
configured secrets, indefinitely, with no error surfaced to the user
beyond a downstream
KeyErrorin whatever script needed the key. -
Origin: on the Dominion Hetzner deployment, a scheduled run's own
agent reported: "Your trading data credentials (Polygon, Finnhub, and the
others) aren't reaching today's scheduled runs, even though they're
correctly set up." Confirmed for two consecutive days —
collect_price.py/grade.py/conviction.pyall failed withKeyError: 'SECRET_POLYGON_API_KEY'— while the identical workflow worked correctly whenever driven interactively from chat.
Workflow secrets are stored per-user at
_users/<userID>/workflow_secrets/<sha256(workflowPath)>.json
(AES-256-GCM encrypted). Both scheduled-run call sites in
agent_go/cmd/server/scheduler.go (the Pulse lifecycle step runner and the
main scheduled workshop-turn loop) invoked startSessionInternal(ctx, reqMap, sessionID, "", nil) — a hardcoded empty user ID. With no user in
the synthetic request's context, GetUserIDFromContext falls through to
GetDefaultUserID(), the literal placeholder "default". Secret lookup
(loadSelectedSecrets) then resolves against _users/default/, which
never has anything stored — nobody configures a workflow's API keys while
logged in as "default"; they do it from their own real account.
Interactive chat sessions never hit this, because they always carry the
real logged-in user's claims through AuthMiddleware.
Confirmed live: _users/ac513919.../workflow_secrets/ had the real
Polygon/Finnhub keys, correctly stored under the actual creating user's
account; _users/default/ had no workflow_secrets directory at all.
Nothing recorded who created or owns a workflow or a schedule —
WorkflowManifest, WorkflowSchedule, and ScheduleContext had zero
owner/created_by/user_id fields, so the scheduler had no data to
resolve the correct identity from even if it had tried.
-
WorkflowManifestgainsCreatedBy, stamped from the authenticated request's user ID inhandleCreateWorkflowManifest(the sole call site ofNewWorkflowManifest) at creation time. -
ScheduleContextgainsOwnerUserID, threaded frommanifest.CreatedByinbuildScheduleContext(the single place a manifest becomes aScheduleContextbefore eitherstartSessionInternalcall site), which now passessctx.OwnerUserIDinstead of"". - Purely additive: a manifest created before this field existed keeps
today's already-broken
"default"fallback until backfilled — not a regression for any other workflow. - The one existing production workflow
(
Workflow/tectonicusadaytrading) was manually backfilled with its real owner's user ID directly in itsworkflow.jsonon the server (timestamped backup left in place), since the field didn't exist when it was originally created.
-
TestBuildScheduleContextThreadsOwnerUserID— confirmsCreatedBythreads intoOwnerUserID, and that an emptyCreatedBy(a legacy manifest) safely stays empty rather than erroring. -
TestHandleCreateWorkflowManifestStampsCreatedBy— confirms the HTTP handler actually stamps the authenticated request's real user ID, not a hardcoded or inferred value. - Both fail to compile without the fix (confirmed via
git stash); fullcmd/servertest suite passes. - Deployed to
trader.tectonicmarkets.com(dominion-agentrebuilt and restarted); confirmed healthy post-deploy, and confirmed the live workflow'sworkflow.jsoncorrectly carriescreated_byafter the manual backfill. - Not yet confirmed against an actual live scheduled fire (deliberately — manually triggering a real run would place real paper trades and consume real market-data API calls; left for the next natural schedule or an explicit user-requested manual trigger).
Auto-synced from docs/ on main. Edit there, not here.