Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,53 @@ checkpoints only after stdout and every forwarding destination have accepted an
event. A cursor gap stops with a nonzero exit unless `--on-gap continue` was
selected.

## Trigger test events

`polymorfa trigger` sends a signed test event for a Test number. The event
reaches your webhooks, event history, and a running `polymorfa listen` with
`source: "test"`, and does not change the Test number. Real numbers are
refused. Each project can trigger 30 test events per minute. It requires a
server API key with `sandbox:write` (`sandbox:read` for `--list`) and Test
numbers access.

Run a listener in one terminal:

```shell
polymorfa listen --project PROJECT_ID --forward-to http://127.0.0.1:3000/webhooks
```

Trigger events in another:

```shell
polymorfa trigger --list --project PROJECT_ID
polymorfa trigger message.received --project PROJECT_ID --session my-test-number --text "hi"
polymorfa trigger message.received --project PROJECT_ID --session my-test-number \
--override mediaType=image --override caption=look
polymorfa trigger message.ack --project PROJECT_ID --session my-test-number --override ackStatus=read
polymorfa trigger message.failed --project PROJECT_ID --session my-test-number
polymorfa trigger call.received --project PROJECT_ID --session my-test-number --override video=true
polymorfa trigger session.restriction_updated --project PROJECT_ID --session my-test-number \
--override restrictionActive=false
polymorfa trigger template.status --project PROJECT_ID --session my-test-number \
--override templateStatus=REJECTED --override reason=INVALID_FORMAT
polymorfa trigger bansafe.enforcement --project PROJECT_ID --session my-test-number
```

The trigger prints the event ID. Without `--forward-to`, the listener prints
the same line (`message.received <eventId>`) when the event arrives; with
`--forward-to`, it prints nothing on success unless you add `--json` together
with `--forward-secret-out <file>` (JSON forwarding requires the secret file),
which writes one JSON line per event. Fixtures are
`message.received`, `message.ack`, `message.failed`, `call.received`,
`call.missed`, `call.ended`, `session.status`, `session.restriction_updated`, `template.status`,
`bansafe.enforcement`, and `bansafe.risk_changed`. `--override key=value`
sets one payload field and can be repeated; `--text` and `--from` are
shortcuts. `video` and `restrictionActive` accept only `true` or `false`;
`durationSeconds` accepts a whole number. Set `restrictionActive=false` to
test the end of a restriction. `--from-session OTHER_TEST_NUMBER` sends a real simulated text from
another Test number in the project instead, producing an ordinary
`message.received` event you can reply to. Use `--json` for one JSON document.

## MCP listener controls

The package includes a standards-based stdio MCP server for Codex and Claude:
Expand Down
80 changes: 80 additions & 0 deletions docs/internal/2026-09-22-trigger-fixture-parity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Trigger fixture parity

Resolved on 2026-09-23: SDK PR #290 merged as
`2b693964305b91dc34b9092ca5774055c7e47d88` and published
`@polymorfa/sdk@0.1.0-dev.20260923093259`. CLI PR #15 now pins that exact
registry artifact in its manifest and lockfile. A clean install and the full
CLI verification suite passed on the branch merged with current `dev`.
The notes below record the earlier local repair and its then-open dependency.

Local repair of CLI #15 at `67b1c0f43568c015c779ebf2c6475237f7b980a8`.
Not published or release-ready. The API contract checked is
`polymorfa/polymorfa@63111fec728ac3ebc9a825ea57ebc4c592abdafc`.

The API lists `session.restriction_updated`, but the CLI's pinned SDK
`0.1.0-dev.20260922102711` omits it from the fixture union. The CLI consequently
refuses an event that `trigger --list` prints. Its override parser also treats
`restrictionActive=false` as a string. This repair types the override as a
boolean and tests both starting and ending a restriction through the command
and HTTP request.

## SDK dependency

Companion SDK work is based on `polymorfa/sdks@8392f66b4df0b0fee3403e27e3d2914516b0e243`,
branch `fix/test-event-fixture-contract-20260922`. It adds the fixture,
`restrictionActive?: boolean`, and the API's `call_restricted` member of
`callEndReason`. It stores the four relevant OpenAPI schemas, source commit,
and source hash in `contracts/testing-events.json` and checks the fixture list
against that snapshot.

CLI validation uses a tarball built from that local SDK source. The package
manifest and lockfile intentionally still pin the published dependency. A
clean install of that old version cannot build this repair because its types
lack `restrictionActive`. Publish and inspect the companion SDK artifact, then
update the CLI's exact dependency and lockfile and repeat normal verification.
Do not replace the dependency with a local alias or invent a registry version.

The three BanSafe event retirements on monorepo branch
`fix/declared-webhook-events` are not in this API baseline. When that change is
integrated, update this contract, the SDK fixture list, CLI examples, and tests
together. This repair retains the two test fixtures the pinned API accepts.

## Runtime and authority

The API mounts trigger and fixture-list routes under `/messaging/testing`
when a simulated Sandbox client is configured. List requires `sandbox:read`;
trigger requires `sandbox:write`. Project/team credentials are accepted by the
API; client tokens are denied. The CLI's existing command specifically uses
its server-API-key path and requires an explicit `--project`.

Both routes check the live project and unified `test-numbers` feature.
This feature is a beta with release flag `release-test-numbers` and explicit
team enrollment. Missing enrollment, disabled release, or failed authority
does not grant access. No flag, credential, enrollment, or environment setting
changes in this repair.

Generated events use the test publication path and cannot change number
state. A real number is rejected. `--from-session` only permits
`message.received`, text-only overrides, and a different Test number in the
same project. The API limits triggering to 30 requests per project per minute.

Errors use the existing CLI mapping: validation/configuration exit 2,
authentication/authorization exit 3, not found/conflict exit 4, and rate limit,
network, timeout, or server failure exit 5. This command passes no idempotency
key, so the SDK does not automatically retry its POST. An uncertain response
must not be described as failed delivery. No new retry behavior is introduced.

## Impact and release checks

| Part | State | Evidence or remaining work |
| ---------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| API | Unaffected | Existing fixture and schema at the pinned revision; no handler, scope, or response change. |
| SDKs | Updated locally; publication blocked | Companion TypeScript catalog and override types, serializer tests, exact schema supplement, README. No new API method or other-language implementation is introduced. |
| CLI | Updated locally; dependency blocked | Boolean parser and command regression tests. Await the inspected published SDK, then update the exact pin and lockfile. |
| Docs | Updated locally | CLI README and SDK README cover the fixture and boolean input. Mintlify `docs/sandbox/test-events.mdx` already documents this existing API behavior. No shipped release announcement is added. Add CLI usage to public docs when the CLI is actually released. |
| Feature releases | Existing authority unchanged; live availability unverified | Existing Test numbers beta, targeting, enrollment and operational controls still apply. No provider or release setting was changed. |
| Admin | Unaffected | Test fixtures add no durable setting or grant. Existing Test numbers release/enrollment and webhook controls remain the authority; generated events cannot create state needing a new staff action. |

Build and focused tests exercise a local HTTP receiver using the actual packed
SDK. They do not establish deployed beta availability, real webhook delivery,
listener delivery, or package publication. No automated reviews were requested.
13 changes: 13 additions & 0 deletions docs/internal/2026-09-23-trigger-launch-docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Prepared CLI trigger documentation

`launch-docs/cli-trigger.mdx` is an internal insertion snippet for `docs/sandbox/test-events.mdx`, after its TypeScript SDK example and before the fixture list. The CLI is unpublished, so do not add the snippet or a CLI changelog entry to public Mintlify until a released CLI artifact includes this command, its installed behavior is checked, and the Test numbers beta audience can use the deployed API path.

The snippet follows the CLI implementation and README at `polymorfa/cli` PR #15, SDK version `0.1.0-dev.20260923093259` from SDK merge commit `2b693964305b91dc34b9092ca5774055c7e47d88`, and the existing Test events guide. A clean CLI install resolved the exact SDK registry artifact. `npm run verify` passed on the branch merged with CLI `dev`: 635 tests in 73 files, build, typecheck, formatting, lint, pack check, and production audit. Compiled `trigger --help` confirms the snippet's flags and fixture name. The command tests exercise local HTTP requests, including typed `restrictionActive=false`, refusal paths, and no-request validation. No deployed API, webhook, event history, live listener, or released CLI install was exercised.

At publication, verify the released CLI version and installed `trigger --help`, then insert the snippet into the existing guide. Render the page at mobile and desktop widths, run Mintlify broken-link and validation checks, and date a customer changelog entry for the available release. Confirm the `release-test-numbers` gate, team enrollment, Test number, and deployed API route for the intended audience. No flag or entitlement change is part of PR #15.

Proposed changelog copy, with date set when customers can use the CLI:

> The Polymorfa CLI can list Test event fixtures and trigger signed events for a Test number. It also sends a simulated message from another Test number with `--from-session`. See [Trigger test events](/sandbox/test-events).

API: unchanged by this CLI work; the existing testing route and scopes remain authoritative. SDK: fixture and override types updated in SDK PR #290, then published under the exact version above. CLI: command, README, and tests updated in PR #15. Docs: CLI README and this internal snippet updated; public insertion remains a release gate. Feature releases: existing Test numbers beta access and enrollment remain; live availability is unverified here. Admin: unchanged because this command adds no staff control.
14 changes: 14 additions & 0 deletions docs/internal/launch-docs/cli-trigger.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Trigger with the CLI

Use a server API key with `sandbox:write` and a project with Test numbers access. Listing fixtures needs `sandbox:read`.

```sh
polymorfa trigger --list --project PROJECT_ID
polymorfa trigger message.received --project PROJECT_ID --session my-test-number --text "hi"
polymorfa trigger session.restriction_updated --project PROJECT_ID --session my-test-number \
--override restrictionActive=false
```

The command prints the event type and ID returned by the API. The event also appears in event history and reaches subscribed webhooks with `source: "test"`. A real number is refused without sending an event.

To send a simulated message from another Test number in the same project, use `--from-session OTHER_TEST_NUMBER` with `message.received`. That sends a message you can reply to; the named fixtures above only generate events.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@modelcontextprotocol/server": "2.0.0",
"@napi-rs/keyring": "1.3.0",
"@oclif/core": "^4.13.5",
"@polymorfa/sdk": "0.1.0-dev.20260922115749",
"@polymorfa/sdk": "0.1.0-dev.20260923093259",
"jq-wasm": "3.0.0-jq-1.8.2",
"zod": "4.2.0"
},
Expand Down
Loading