Skip to content
Draft
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
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ node_modules/
package-lock.json
*.tgz
.sdk-source/

# Preserve the upstream golden vectors byte-for-byte.
test/fixtures/machine-credentials-v1.json
40 changes: 23 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ polymorfa version
## Requirements

- Node.js 22 or newer
- A Polymorfa organization API key or exact-project token for developer requests
- A Polymorfa team key or exact-project token for developer requests
- A server API key or short-lived client token for Messaging requests

## Development installation
Expand Down Expand Up @@ -65,7 +65,7 @@ access but do not use your Polymorfa credentials.
## Authentication profiles

Until the backend exposes a revocable CLI device-authorization flow, login
accepts an organization API key or exact-project token through standard input:
accepts an team key or exact-project token through standard input:

```shell
printf '%s' "$POLYMORFA_API_KEY" | \
Expand All @@ -85,6 +85,12 @@ Secret Service. A keyring failure stops the command; the CLI never silently
falls back to plaintext. `auth status` reports local secure-store availability
in this development slice and does not yet claim remote identity validation.

Treat all Polymorfa credentials as opaque strings. Pass them unchanged; never
parse them or assume a fixed length. Credential columns must store at least 512
characters, preferably unrestricted text. Client-token length varies with its
bindings, Customer block and signing key ID. Local prefix, encoding and checksum
checks do not authenticate a credential; the service checks live authority.

Environment credentials take precedence over the active profile for automation.
An explicit `--profile <name>` takes precedence over environment credentials.

Expand Down Expand Up @@ -182,7 +188,7 @@ your shell to its startup file if you want completion in later sessions.

## Inspect sessions

Use an organization API key with `sessions:read` to inspect stored session
Use an team key with `sessions:read` to inspect stored session
metadata:

```shell
Expand All @@ -197,7 +203,7 @@ Use a session ID from the list for `view` or `status`; these commands do not
accept `--project`. `status` reads the stored status and optional reason from
the session record. It does not probe the device or wait for a connection.
Key metadata listing and revocation are available through `key list` and
`key revoke`; the CLI does not mint or rotate organization keys.
`key revoke`; the CLI does not mint or rotate team keys.

## QuickLinks

Expand All @@ -215,7 +221,7 @@ The request accepts `customerId`, `externalId`, and `configuration`. See
[Guided session creation and configuration](#guided-session-creation-and-configuration)
for the configuration fields.

Inspect or cancel a link with an organization API key or an exact-project
Inspect or cancel a link with an team key or an exact-project
token that has `quicklink:manage`:

```shell
Expand Down Expand Up @@ -418,7 +424,7 @@ header.

### Flow drafts and provider lifecycle

Flow commands require a project scope and an organization API key or project
Flow commands require a project scope and an team key or project
token. Reads use `sessions:read`; mutations use `sessions:manage`.

```shell
Expand Down Expand Up @@ -501,7 +507,7 @@ linked to another project; the API checks that the credential can access it.

### Official API observations and templates

The `cloud` commands require an organization API key or a project token with the
The `cloud` commands require an team key or a project token with the
listed scope. Client tokens cannot use these commands. Server-side feature
access still applies: an installed command does not enroll a Number or enable a
beta feature.
Expand Down Expand Up @@ -1151,7 +1157,7 @@ sox greeting.wav -t raw -r 16000 -e signed -b 16 -c 1 - | \

Polymorfa checks every call against the team's call policy before the
destination rings. `calls policy` and `calls opt-outs` read and change that
policy and require an organization API key (`POLYMORFA_API_KEY` or a profile).
policy and require an team key (`POLYMORFA_API_KEY` or a profile).
A project token used as the API key reaches the API, which refuses it with
`403` (exit code 3). A client token is not a Platform credential, so the CLI
refuses the command before sending a request (exit code 2).
Expand Down Expand Up @@ -1230,9 +1236,9 @@ polymorfa calls check +14155550123 --session support
### Call statistics and export

`calls stats` summarizes calls and `calls export` writes call detail records.
Both accept an organization API key or an exact-project token with the
Both accept an team key or an exact-project token with the
`sessions:read` scope. Pass `--project` to read one project. Without it, an
organization API key reads every project in the organization. A project token
team key reads every project in the organization. A project token
reads only its own project and requires `--project`.

```shell
Expand Down Expand Up @@ -1321,7 +1327,7 @@ or times out, the command keeps the password on screen and exits successfully.
Voice Automation is a beta (`calls.voice-automation`) for enrolled teams only.
For other teams, every change except delete fails with `voice_not_enabled`.
Reads, previews and deletes keep working after a team leaves the beta. The
commands require an organization server API key with `voice:read` (lists,
commands require an team key with `voice:read` (lists,
views, previews) or `voice:manage` (changes).

### Audio library
Expand Down Expand Up @@ -1596,7 +1602,7 @@ request metadata.

## Platform access and security

Organization server API keys can inspect the credential, membership, audit,
Team keys can inspect the credential, membership, audit,
ban, incident, saved QuickLink settings, and project-token metadata made
available by the Platform API:

Expand Down Expand Up @@ -2159,7 +2165,7 @@ status, and safe counters, never primary credentials, listener credentials,
forwarding secrets, or unrestricted payloads.

`polymorfa_session_list` is a read-only discovery tool for one explicit project
UUID. It uses the selected CLI organization API key with `sessions:read` and
UUID. It uses the selected CLI team key with `sessions:read` and
returns session ID, name, stored status, and test-mode flag. It omits phone
numbers, credentials, and message data. The tool does not probe the live device.
Project tokens and Messaging client tokens cannot use this tool. A failed read
Expand Down Expand Up @@ -2371,7 +2377,7 @@ the CLI never creates or confirms a replacement purchase automatically.

### Number tier changes

Tier changes use an organization API key. Quote first, review the credit charge
Tier changes use an team key. Quote first, review the credit charge
and effective time, then confirm that exact quote:

```shell
Expand Down Expand Up @@ -2460,7 +2466,7 @@ polymorfa hybrid-link resume --session NUMBER --expected-revision REVISION
For project and session routing scopes, `--project`, the nearest linked project,
and the selected profile determine the project in that order. A project-token
profile fails when its project differs from the linked directory. Team routing
scope uses an organization API key and ignores directory project links. `quicklink
scope uses an team key and ignores directory project links. `quicklink
availability` shows existing connection status and any QuickLink that can be
resumed.

Expand All @@ -2481,7 +2487,7 @@ transports within the restrictions inherited from the team and project.

### Functions

Functions are project-owned. Select `--project` or use the linked project/profile context. The commands accept an organization API key or a project token; browser client tokens are refused. Access also depends on the team's enabled Functions release and the configured execution region.
Functions are project-owned. Select `--project` or use the linked project/profile context. The commands accept an team key or a project token; browser client tokens are refused. Access also depends on the team's enabled Functions release and the configured execution region.

```bash
polymorfa function list --project PROJECT_UUID
Expand Down Expand Up @@ -2566,7 +2572,7 @@ does not retrieve media or webhook deliveries.

### Spending limits and funding priority

With an organization key carrying `billing:read`, inspect current controls:
With an team key carrying `billing:read`, inspect current controls:

```bash
polymorfa billing limits list --project <project-uuid> --json
Expand Down
2 changes: 1 addition & 1 deletion docs/command-research/call-consent.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ package metadata.
## Credential rules

- `calls policy` and `calls opt-outs` resolve Platform credentials, so they
require an organization API key. The API answers a project token or client
require an team key. The API answers a project token or client
token with `403 permission_denied`, which exits with code 3.
- `calls permission get` and `calls check` require a server API key. The CLI
refuses a Messaging client token before sending a request, because the API
Expand Down
4 changes: 2 additions & 2 deletions docs/command-research/calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ internal SDK module.
Messaging client; the CLI builds that client from the Platform environment.
`calls settings set --expected-revision` sends `expectedRevision`; a stale
revision returns 409 `state_conflict`, which exits with code 4.
- `calls stats` and `calls export` accept an organization API key or an
- `calls stats` and `calls export` accept an team key or an
exact-project token (`sessions:read`), resolved like the developer
commands. `--project` (or a project token, which requires it) reads one
project; an organization key without `--project` reads the whole
project; an team key without `--project` reads the whole
organization. `--owner` still overrides the inferred owner.
- `calls retention` resolves a team API key or a project token
(`resolveTeamSettingEnvironment`), from the environment or a profile, with
Expand Down
2 changes: 1 addition & 1 deletion docs/command-research/customers.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Customer command contract

The Customer command family maps the complete public Customers surface in the
Platform contract. Every request uses an organization server API key and an
Platform contract. Every request uses an team key and an
explicit project ID.

| Command | Platform operation |
Expand Down
4 changes: 2 additions & 2 deletions docs/command-research/platform-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ session
```

The management commands use the public typed organization resources on the
unified SDK `Client`. They require an organization server API key. Reads require
unified SDK `Client`. They require an team key. Reads require
`sessions:read`; key revocation and incident acknowledgement require
`sessions:manage`; batch session stop/delete also require `sessions:manage`.
Project tokens and Messaging browser client tokens are rejected before
Expand Down Expand Up @@ -85,7 +85,7 @@ without cursor semantics.
`session-ban list --active` keeps one discovery command while selecting the
SDK's distinct active-only operation. Incident acknowledgement is repeatable,
has no confirmation gate, and sends no body. `acknowledgedBy` may be empty when
an organization key performed the acknowledgement.
an team key performed the acknowledgement.

The original singular Platform operation view was removed. Operation
inspection is console-only at API contract 1600403, and the pinned SDK has no
Expand Down
6 changes: 3 additions & 3 deletions docs/command-research/quicklinks.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ on the hosted page and preserves entitlement boundaries around direct pairing.
| `quicklink view` | `MessagingClient.quickLinks.retrieve` | `GET /messaging/quicklinks/{id}` | Read one link's status and onboarding progress |
| `quicklink cancel` | `MessagingClient.quickLinks.cancel` | `DELETE /messaging/quicklinks/{id}` | Invalidate an unconnected link; initial Number/session cleanup can continue after acceptance |

All three routes require `quicklink:manage`. The API accepts organization keys
All three routes require `quicklink:manage`. The API accepts team keys
and exact-project tokens and scopes project tokens to their own project.

`quicklink create` takes one JSON object from `--input` with `projectId`,
`customerId`, `externalId`, and `configuration`, and rejects other top-level
fields before transport. Presentation and callbacks belong in saved settings
(`widget view|update`). It uses an organization API key; project-token support
(`widget view|update`). It uses an team key; project-token support
for creation is not exposed by this command.

`quicklink view` and `quicklink cancel` accept an organization API key or an
`quicklink view` and `quicklink cancel` accept an team key or an
exact-project token and require explicit project context. Browser client tokens
fail before transport. Cancellation requires TTY confirmation or `--yes` before
a client is constructed. The route does not read an `Idempotency-Key`, so the
Expand Down
2 changes: 1 addition & 1 deletion docs/command-research/voice.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ URL itself with no credential, no redirects, a bounded response, and a timeout.

## Credential rules

- The commands resolve Platform credentials: an organization server API key
- The commands resolve Platform credentials: an team key
(`POLYMORFA_API_KEY` or an API-key profile). Client tokens fail before any
request. The API also accepts project tokens; the CLI does not use them for
these commands, matching `sip-trunk`.
Expand Down
2 changes: 1 addition & 1 deletion docs/development/bansafe-sdk-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ dependency.
The CLI mapping covers all 25 Platform BanSafe operations in the SDK coverage
ledger. The SDK also covers the 10 equivalent Messaging settings routes through
`MessagingClient.banSafe`; the CLI uses the Platform routes for those settings
because BanSafe commands authenticate with an organization server API key.
because BanSafe commands authenticate with an team key.

| SDK operations | CLI commands |
| ------------------------------------------------------------ | ---------------------------------------------------------- |
Expand Down
25 changes: 25 additions & 0 deletions docs/opaque-credentials-cutover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Credential cutover acceptance

API source: polymorfa/polymorfa #647 at f4a82c014e8ea8deb476fce4d81bf27591981c63.
SDK source: polymorfa/sdks #355. CLI credential validation continues to use the
public SDK; it adds no parser or exact-length validator. Tests use the public
20-byte CRC32 opaque-key fixture and check that invalid checksums fail before
secure-storage writes.

The committed SDK dependency predates this contract. Before merging/releasing,
pin the exact accepted SDK registry version and update package-lock.json. A local
candidate tarball can prove behavior but cannot substitute for registry integrity,
matching environment acceptance or the release receipt required by RELEASING.md.
No guessed package version or permissive compatibility fallback is allowed.

Test keys are ordinary project tokens. The CLI never reveals or creates a Test
key and never attempts to infer test-only authority from credential contents.

The copied `test/fixtures/machine-credentials-v1.json` is byte-for-byte identical
to that API source, SHA-256
`7694d8eb61dca6aed69f41392d2e5fae585084e330b276ee6a71844ef9e2365d`.
The CLI accepts the public opaque key vectors through the published SDK, without
adding a second parser. Current registry dependency
`0.1.0-dev.20261004024706` rejects these vectors as legacy-format credentials.
The SDKs thread owns #355. Its accepted registry artifact is the external gate;
this branch keeps the published dependency and does not publish packages.
10 changes: 5 additions & 5 deletions docs/superpowers/specs/2026-08-19-polymorfa-cli-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ collections, orders, compliance, observation policies, webhooks, client tokens,
project templates, project-scoped campaigns, and all 33 signed event payload
schemas plus Platform
organizations, projects, sessions, billing, campaigns, audiences, opt-outs,
media, organization API keys, members, audit logs, session bans, security
media, team keys, members, audit logs, session bans, security
incidents, project-token metadata, saved QuickLink (widget) settings, and batch
session stop/delete. Curated commands do not use the SDK's raw escape
hatch to paper over a missing public contract. The explicit `api` command is
Expand Down Expand Up @@ -585,7 +585,7 @@ group
```

Number pairing uses a persistent hosted QuickLink. `quicklink create` accepts a
JSON request with an organization API key and returns the link URL,
JSON request with an team key and returns the link URL,
`quicklink view` reads its status, and `quicklink cancel` invalidates a link that
has not connected. View and cancel also accept an exact-project token. Saved
QuickLink settings are managed with `widget view` and `widget update`; the CLI
Expand Down Expand Up @@ -814,7 +814,7 @@ bounded concurrency, and machine-readable partial-failure artifacts.

The `flow` top-level command name remains reserved but is not shipped against
this SDK baseline. The separate Platform template and Flow routes require
dashboard JWTs and reject organization keys. The CLI must not collect, persist,
dashboard JWTs and reject team keys. The CLI must not collect, persist,
or replay dashboard session JWTs to bypass that boundary, and neither MCP tools
nor skills may expose those routes. Platform template management and Flow
commands can enter the implementation plan only after the Platform API provides
Expand Down Expand Up @@ -1079,8 +1079,8 @@ slices:
commands, with accepted-work receipts and direct requeue;
- explicit owner-scoped event list/view/replay, webhook CRUD/test/secret
rotation, delivery and attempt inspection, and retry commands;
- persistent QuickLink create with organization keys, view/cancel with
organization keys or exact-project tokens, and no direct session QR fallback;
- persistent QuickLink create with team keys, view/cancel with
team keys or exact-project tokens, and no direct session QR fallback;
- the bounded SSE listener with JSONL and human sinks, fail-closed gap handling,
cumulative acknowledgement, checkpointed reconnects, exact-byte local
signing, and redirect-safe forwarding;
Expand Down
18 changes: 10 additions & 8 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"verify": "npm run format:check && npm run lint && npm run typecheck && npm test && npm run build && npm pack --dry-run --ignore-scripts && npm run audit:prod"
},
"dependencies": {
"@modelcontextprotocol/server": "2.0.0",
"@modelcontextprotocol/server": "2.3.1",
"@napi-rs/keyring": "1.3.0",
"@oclif/core": "^4.13.5",
"@polymorfa/sdk": "0.1.0-dev.20261004024706",
Expand Down Expand Up @@ -175,7 +175,7 @@
"description": "Resolve phone numbers and usernames to Polymorfa user IDs."
},
"key": {
"description": "Inspect and revoke organization API keys."
"description": "Inspect and revoke team keys."
},
"label": {
"description": "Manage Messaging labels and chat assignments."
Expand Down
Loading
Loading