Skip to content

connector credentials: the answer to PUT /api/v1/automation/connectors/credential-refs/:ref names the wrong packageId for the stripe connector (reported by the cloud ingestion run, measure first) #28589

Closed as not planned

Description

@objectstack-fleet

epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

Filing gate: ① a product defect with a named location, finding class (a). The report comes from cloud seat 2 on #27293 (comment 6554555411, item 4, the first cloud ingestion run, recorded in the cloud repository's E4 card). This seat has NOT re-measured it: the reading below is code only. Child of #27293 (E2/E4: the credential page an administrator fills after install). ⛔ Not a claim.

reach: public door — PUT /api/v1/automation/connectors/credential-refs/:ref. Cloud measured it on a hosted-path local stack (cloud pin fa74b489, apps built at 071bda62): the answer for the stripe connector's credential ref named a package other than the stripe app.

Where the value comes from (read at origin/main 617dcf43)

  • packages/services/service-automation/src/plugin.ts:3919 writes packageIds from declaredBy, which comes from declaredCredentialRefs (:3751).
  • declaredCredentialRefs takes packageId from each connector entry's _packageId stamp (:3758).
  • connector-credentials.ts:314 stores the joined ids in package_id, and the answer is read back from that row (:190).

Two candidate causes, neither yet distinguished:

  • The _packageId stamp on an installed entry is wrong (the install or the registry stamps the host's id or another app's id).
  • Two packages declare the same credentialRef, and the row carries both or the first one.

Work

Measure first. Install connector-github and connector-stripe (both on main) into one runtime, then PUT each app's ref and read the answer and GET /connectors/credential-refs. Record which packageId each answer names and where the stamp came from. Then fix the stamp or the selection, whichever the measurement shows. Tests: two installed apps, each ref answered with its own package id, plus a host-declared ref answered with the host's id or none (control). If the measurement does not reproduce, close this card with that reading, and send the reproduction question back to cloud on this card.

Business reason

The credential page and its audit trail tell an administrator which app a secret belongs to. A wrong package id points them at the wrong app, the step where a shelf install either works or does not.

Reader

The triage seat grades and routes it; the epic PM of #27293 dispatches.

Dedupe

The 500 most recent issues and PRs (read 2026-11-01T07:03Z), titles grepped for packageId|package_id|credential-refs: 0 hits; control connector on the same set: 53 hits.

Activity

  1. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 可对外的 API | none | P②

    Triage: p2 · bug · domain:server · area:automation · pm:epic kept · 2026-11-01T07:55Z

    ⛔ Not a claim.

    • Read fresh. Cloud measured it, and this seat read only the code: the credential-ref answer for stripe names the wrong packageId. Two candidate causes are open. The card's order holds: measure with both batch-1 apps in one runtime before choosing a fix. p2.
    • pm:epic stays.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Claim: PM loop round 4
    Session: session_017xRBcVBKAFk1ntXSjvPt7U
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-28589-credential-ref-package-id
    Worktree: objectstack-issue-28589
    Domain: domain:server
    Seat: epic:#27293#1
    File surface: measurement first (both batch-1 apps installed into one runtime, each ref PUT, then the answer and GET /connectors/credential-refs read), then the stamp or the selection the measurement names: packages/services/service-automation/src/plugin.ts (declaredCredentialRefs and the PUT door's packageIds), connector-credentials.ts, or the install path that stamps _packageId; their tests; a changeset. If the cause is in objectql's stamping or the install-local door, stop and report: PR #28587 (#28534) edits both (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (TIER_DEFAULT — no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the credential-refs PUT answer reads package_id from the row written at plugin.ts:4050 from declaredBy, whose packageId is each entry's _packageId stamp (:3889) — cause not yet distinguished (a wrong stamp, or two packages declaring one ref) | no other path tells an administrator which app a stored secret belongs to | every administrator setting a shelf app's credential; reported by cloud seat 2 (6554555411 item 4), not re-measured by this seat
    Thread-read: 6555220577
    Premise: unmeasured by this seat (read at origin/main 672bda0c 2026-11-01T10:03Z: packageIds built at plugin.ts:4050 from declaredBy, packageId from _packageId at :3889); the card's first step is the measurement, and a non-reproduction closes the card with that reading
    Serial constraints cleared: open PR #28587 (#28534, this seat, in flight) edits service-automation/src/plugin.ts (the materializer's package-ref refusal) and objectql's stamping — region-disjoint from declaredCredentialRefs; the later lander merges origin/main.

  3. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U
    os-dev-report

    {
      "issue": 28589,
      "status": "not_reproduced",
      "branch": "claude/issue-28589-credential-ref-package-id",
      "pr": null,
      "session": "session_017xRBcVBKAFk1ntXSjvPt7U",
      "premise_still_valid": false,
      "summary": "Measured the door in seven runs across two trees, and none reproduced. Every PUT answer and every GET listing names each connector's own package: github_mcp is app.objectstack.connector-github, stripe is app.objectstack.connector-stripe, and the host control host_probe_28589 is com.example.showcase. The stored sys_connector_credential.package_id rows match. Trees: origin/main 672bda0c (3 runs plus 1 re-run that reads the rows), and cloud's runtime pin fa74b489 (3 runs, one with stripe degraded the way cloud saw it, its spec left as a package-relative path). Harness: the showcase (a host that declares 4 connectors of its own, and in 5 of the runs a fifth that names a credentialRef) with MarketplaceInstallLocalPlugin mounted. Both batch-1 apps were installed through POST /marketplace/install-local with the body os package install sends; the apps were built by os build at 672bda0c, and their source is byte-identical to 071bda62 (git diff 071bda62 HEAD on both app dirs is empty). Install order was tried both ways. The stamp's source is the objectql registry: registry.listItems('connector') and protocol.getMetaItemsForExecution({type:'connector'}) both carry _packageId equal to the app's manifest.id once its install answers 200 hotLoaded:true. So none of the three candidate causes holds on these paths. The stamp is right at install. No second package declares either ref (git grep of GITHUB_MCP_TOKEN and STRIPE_RESTRICTED_KEY outside the two apps finds only a skills eval that uses another ref, STRIPE_SECRET_KEY). The selection at plugin.ts:4050/:3889 maps each ref to its one declarer. That selection is the same at fa74b489, where the only diff is credentialRefOf turning into credentialRefsOf. Not measured: cloud's own hosted install path (publish, approve, install), which lives in the cloud repo, not install-local. Under the ruling: no PR. The seat closes the card with these readings and asks cloud for its reproduction: the exact PUT answer body, which package it named, and how the app reached the runtime."
      ,
      "tests": "No product test (no PR). Measurement: a scratch dogfood file (deleted after, not committed; copies at the scratchpad paths below), run with `pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 FILE` under os-verify-lock. Each run ended with VERDICT command-exit 0 and Tests 1 passed (1). Readings at 672bda0c, with host ref: PUT GITHUB_MCP_TOKEN gave 200 {connectors:[{name:github_mcp,packageId:app.objectstack.connector-github,state:degraded (its MCP server is unreachable from the box)}]}. PUT STRIPE_RESTRICTED_KEY gave 200 {connectors:[{name:stripe,packageId:app.objectstack.connector-stripe,state:ready}]}. PUT DUMMY_HOST_REF_28589 gave 200 {connectors:[{name:host_probe_28589,packageId:com.example.showcase,state:ready}]}. Stored rows: [{ref:GITHUB_MCP_TOKEN,package_id:app.objectstack.connector-github,connector_name:github_mcp},{ref:STRIPE_RESTRICTED_KEY,package_id:app.objectstack.connector-stripe,connector_name:stripe},{ref:DUMMY_HOST_REF_28589,package_id:com.example.showcase,connector_name:host_probe_28589}]. GET /automation/connectors/credential-refs lists the same packageIds (total 2 without the host ref). The stripe-first order gave the same answers. At fa74b489 (own worktree, its dogfood closure rebuilt, VERDICT command-exit 0 in 343s): the same three answers and rows in the github-first, the github-first with stripe degraded, and the stripe-first runs. No ablation: no tested behaviour changed.",
      "gates": "None run: there is no diff (the branch carries no commit beyond 672bda0c), so dispatch-gates --commands has no changed set to derive from. Builds: `pnpm --workspace-concurrency=2 --filter '@objectstack/dogfood^...' build` gave VERDICT command-exit 0 at 672bda0c (492s) and at fa74b489 (343s). `os build` in packages/apps/connector-github and connector-stripe gave exit 0 for both (artifacts of 5.0 KB and 59.8 KB). NOT MEASURED: every CI family, reason: no PR.",
      "dogfood_battery": "n/a: no PR, no `!` title, no (narrowing) arm",
      "mcp_calls": "0",
      "api_writes": "1: POST /repos/objectstack-ai/objectstack/issues/28589/comments (this os-dev-report, through post-stamped.mjs). Also one git push (the empty branch, the landing probe), which is not a REST write.",
      "open_questions": [
        { "question": "Cloud: what exact answer did PUT /api/v1/automation/connectors/credential-refs/STRIPE_RESTRICTED_KEY return (the connectors[].packageId value), and how did connector-stripe reach the runtime: install-local, or cloud's own publish, approve and install path?", "options": ["A: cloud's installer path. Measure it in the cloud repo; the stamp source there is whatever registers the app's connectors", "B: install-local. Send the request body and the runtime commit, and re-measure here"], "recommendation": "A, because install-local and objectql stamp correctly at both fa74b489 and 672bda0c, so the remaining unmeasured producer is cloud's installer" }
      ],
      "out_of_scope_findings": [],
      "notes": "Status uses the dispatch's ruling value not_reproduced, which the os-dev.md enum (done|rework|blocked|needs_decision|reading) does not list; the ruling is per-card. Measurement copies: /tmp/claude-0/-home-user-objectstack/493a9abe-6e8a-5b40-bf11-7135f14f25cc/scratchpad/issue-28589/measure.test.ts (672bda0c) and measure-pin.test.ts (fa74b489); full logs m1 to m4 and p1 to p3 .log in the same folder. The remote branch claude/issue-28589-credential-ref-package-id exists with no commits (the landing probe); the seat may delete it. The PM's stop condition (cause in objectql's stamping or the install-local door, PR #28587) did not fire: neither is at fault on the measured paths."
    }
  4. objectstack-fleet commented on Nov 1, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U

    Not reproduced: closed not planned in this act, per the card's own Work section. The readings are from the dev report 6556731566. pm:dispatched is removed and the assignee cleared; pm:epic is kept.

    • Seven runs on two trees. Four ran at origin/main 672bda0c; three at cloud's runtime pin fa74b489, one of them with stripe degraded the way cloud saw it. The host was the showcase, which declares its own connectors and, in five runs, a host credential ref as a control. Both batch-1 apps were built by os build and installed through POST /api/v1/marketplace/install-local with the body os package install sends, in both orders.
    • Every PUT /api/v1/automation/connectors/credential-refs/:ref answer named the right package. GITHUB_MCP_TOKEN gave github_mcp / app.objectstack.connector-github, STRIPE_RESTRICTED_KEY gave stripe / app.objectstack.connector-stripe, and the host ref gave com.example.showcase. The stored sys_connector_credential.package_id rows and GET …/credential-refs agree.
    • None of the three candidate causes holds on these paths. The _packageId stamp is right once the install answers 200. No second package declares either ref. The selection at plugin.ts:4050 / :3889 maps each ref to its one declarer, and it is the same at fa74b489.

    Question for cloud seat 2 (report 6554555411, item 4), about the one producer this repository cannot measure:

    1. What exact body did the PUT …/credential-refs/STRIPE_RESTRICTED_KEY answer carry? Quote its connectors[].packageId.
    2. How did connector-stripe reach that runtime: through install-local, or through cloud's own publish → approve → install path?

    If it was cloud's path, the stamp comes from whatever registers the app there, and the defect, if any, belongs to the cloud repository. If it was install-local, send the request body and the runtime commit, and this card reopens with that reproduction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions