Commit 14f80e2
Fixes #20590
Clause-②: no
## What this changes
This is the `domain:services` face of triage's direction A on this card
(ruling `5891721503`, "Direction: A, taken whole"), scoped by the claim
`5891908897`. It carries two guidance edits and nothing else. Nothing
new is withheld on read.
1. **The `http` action descriptor's `configSchema`**
(`packages/services/service-automation/src/builtin/http-nodes.ts`). The
`url` field read "Target URL" and the `headers` field read "Request
headers". Both now say that the value is stored in the flow definition,
that a flow definition is served to every member who can read flows, and
that an outbound credential goes to a `connector_action` on a
declarative connector whose `auth.credentialRef` names the secret.
*(Seat's correction after patch round 1: that holds for `headers`. For
`url`, a query-string key goes to a declarative `rest` connector with
`api-key` auth (`paramName`, `auth.credentialRef`), and a webhook whose
path is the secret goes to a token-authenticated connector such as
`slack`, since no `credentialRef` variant carries a path-borne secret.)*
Of this node's config, only `signingSecret` is withheld on read
(`FLOW_NODE_CREDENTIAL_KEYS`), so `url` and `headers` are served as
authored. A code comment beside the two fields records that.
2. **The showcase's webhook-url teaching site**
(`examples/app-showcase/src/automation/flows/index.ts`, the `slack_post`
node in `showcase_fan_out_notify`). The branch comment used to teach
"post through an incoming webhook". It now sends a real post through a
connector, as `TaskCompletedSlackFlow` already does. A comment directly
above the placeholder url says that the url is served with the flow
definition to every member who can read flows, and that an
incoming-webhook url's path is its secret, so a real one never goes
there.
A changeset (`patch`, `@objectstack/service-automation`) covers the
descriptor text, which ships in that package's `dist`. The showcase is
`private`, so it takes no changeset.
## Mechanism assumptions, measured at `992c9ac87`
**A1: where the descriptor text reaches an author.**
`AutomationEngine.getActionDescriptors()` backs the runtime automation
domain's `GET /automation/actions`, which is the designer palette's
feed. The client SDK calls it as `automation.listActions`. The
`configSchema` it serves is what the Studio property form is built from
(`io-node-form-zod-ledger.test.ts` header).
- Measured with a one-shot probe (not committed): the real runtime
`HttpDispatcher`, over a real `AutomationEngine` with
`installBuiltinNodes`, answered `GET /automation/actions` with `200` and
17 descriptors. The `http` descriptor's `url` and `headers` descriptions
are the new text.
- NOT MEASURED: how the Studio renderer shows a field `description`.
That lives in the sibling UI repository, which is outside this run's
scope.
- **`connector_action`:** its descriptor publishes **no**
`configSchema`. That is deliberate: the executor reads only the
`FlowNodeSchema.connectorConfig` sibling block. The same probe answered
`configSchema: null` for it, and `io-node-form-zod-ledger.test.ts` and
`config-schemas.test.ts` both pin it. So there is no services-side
`input` describe to steer. The `connectorConfig.input` describe lives in
`packages/spec`, which is #20654's face.
- **Wording:** the text matches the spec describes #20654 will carry, in
substance: a flow definition is served to every member who can read
flows, and an outbound credential goes to a declarative connector's
`auth.credentialRef`. It also agrees with the flows guide sentence
#20663 landed. The exact words are this PR's own.
**A2: the showcase site.** The showcase could not simply take the
connector route.
- `showcase_fan_out_notify` is the platform checklist's `parallel` +
`http` fixture (`docs/qa/platform-checklist/areas/automation.json`,
`automation.flow-node-type-matrix`). That item locates the `http`
variant's step in this flow's runs. Turning `slack_post` into a
`connector_action` would move the tested surface.
- A provider-bound connector with a real `credentialRef` fails the boot
when the reference does not resolve (`resolveInstanceAuth`, ADR-0097
§3). That is why every showcase instance declares `auth: { type: 'none'
}`. Adding one would also touch `src/system/connectors/index.ts`, which
is outside this card's file surface.
- So the url stays, and the comment beside it says plainly that it is
served. The edit is comment-only: with whitespace minified, esbuild
0.28.1 compiles the file at the merge base and at `992c9ac87` to
byte-identical JavaScript (sha256 prefix `6197a04e663ec0d8`, 31,595
bytes). The positive control is a one-character change in the same url,
which does change the output.
## Tests, at `992c9ac87`
- `@objectstack/service-automation`: 154 test files and 1,913 tests
passed (`vitest run --maxWorkers=2`). `typecheck` passed, including
`check:test-typecheck`. `tsconfig.test.json` compiles
`http-nodes.test.ts` (counted with `--listFiles`).
- New pin in `http-nodes.test.ts`: the `url` and `headers` descriptions
each name `auth.credentialRef` and `connector_action`. It asserts the
named route, not the prose.
- **Ablation**, with the fix committed first, through
`scripts/ablation-replace.mjs` in wrap mode plus a shell trap. The
mutation put both descriptions back to their pre-fix text. On disk:
`auth.credentialRef` count 2 to 0, and the old one-line fields 0 to 1
each. Result: exactly the two new cases failed, "2 failed, 8 passed",
with the messages "expected 'Target URL' to contain
'auth.credentialRef'" and "expected 'Request headers' ...". Restore
proof: blob `67f3d9d05a64` equals the HEAD blob, and `git diff HEAD` is
empty. The test imports the source file directly, so no build sits in
the path.
- **Published surface:** the built `dist/index.js` and `dist/index.cjs`
each carry the new text twice, and the old `headers` description zero
times. The positive control, the unchanged `method` description, appears
once in each. `files[]` is `dist`, `README.md`, `CHANGELOG.md`.
- `@objectstack/example-showcase`: `typecheck` passed, and the full
suite passed: 29 files, 385 tests.
- Lint, narrowed to the three touched `.ts` files: 3 files, 0 errors, 0
warnings (eslint `--no-inline-config --format json`). The narrowing is
sound for three reasons. `--print-config` resolves a rule set for each
file, so none is ignored. No `parserOptions.project` or `projectService`
is set, so linting is not type-aware. A diff therefore cannot move any
untouched file's verdict. The full `pnpm lint` is CI's.
## Gates
`node scripts/pm/dispatch-gates.mjs --commands` at `992c9ac87` derived
63 commands. All 63 were run with each exit code captured before any
pipe, and all exit 0. `--ran` reconciles "63 derived, 63 run, 0
NOT-MEASURED, 0 UNRUN", with every code recorded.
- `check:dual-build-cjs-loads` and `check:type-check-debt` first
answered `PREREQUISITE NOT MET` (exit 3). They were re-run after a turbo
build of every package, and both then passed.
- The four roster families were run separately, and each exited 0: `node
scripts/check-changeset-fixed.mjs`, `pnpm check:authz-resolver`, `pnpm
check:error-code-casing` and `pnpm check:filter-alias-parity`.
- The derivation reports that `origin/main` has moved five commits past
this branch's base. None of those commits touches a path in this diff.
## Acceptance notes
- `content/docs/automation/flows.mdx` still lists "an `http` node
posting to an incoming webhook" as the replacement for the retired Slack
`actionType`, in its retired-shapes table. The docs face's PR recorded
the same line. It is outside this card's file surface.
- #20654 (spec describes, and the lint predicate and advisory) and
#20657 (the automation skill) remain open, and each carries its own
face. The flows guide face landed separately.
## Patch round 1 (the seat's append)
- **R1** (at-tier record `5894416988`): `ConnectorInstanceAuthSchema`
has no variant for a secret in the url path, so the `url` describe no
longer sends a path-secret webhook to `auth.credentialRef`. It routes by
shape:
- a query-string key goes to a declarative `rest` connector with
`api-key` auth (`paramName`, `auth.credentialRef`);
- a path-secret webhook goes to a token-authenticated connector (the
`slack` bot token).
- Every named route was verified at source (`connector-auth.zod.ts`,
`plugin.ts` `resolveInstanceAuth`, `rest-connector.ts` `applyAuth`,
`slack-connector.ts`).
- The `headers` describe is unchanged. The code comment no longer claims
the spec describes already match (#20654 is open).
- The changeset lists the three routes.
- **At `695bb749`:** `service-automation` 1913 passed, `typecheck` exit
0. The ablation of the url clause turned exactly the url pin red, with
the headers pin green, and the restore was proven. `dist` carries the
new clause. 63 / 63 derived gates and the 4 ⛔ rosters exit 0.
- **The same over-reach elsewhere:** the landed `flows.mdx` callout and
its retired-shapes row are #20682. #20654 and #20657 carry wording
guards.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 7184436 commit 14f80e2
4 files changed
Lines changed: 82 additions & 6 deletions
File tree
- .changeset
- examples/app-showcase/src/automation/flows
- packages/services/service-automation/src/builtin
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1014 | 1014 | | |
1015 | 1015 | | |
1016 | 1016 | | |
1017 | | - | |
1018 | | - | |
1019 | | - | |
1020 | | - | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
1021 | 1023 | | |
1022 | 1024 | | |
1023 | 1025 | | |
1024 | 1026 | | |
1025 | 1027 | | |
1026 | 1028 | | |
1027 | 1029 | | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
1028 | 1038 | | |
1029 | 1039 | | |
1030 | 1040 | | |
| |||
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
64 | 83 | | |
65 | 84 | | |
66 | 85 | | |
| |||
Lines changed: 34 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
100 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
101 | 126 | | |
102 | | - | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
103 | 135 | | |
104 | 136 | | |
105 | 137 | | |
| |||
0 commit comments