From e5b5f356786987e1ff05d4660f5063a8da818591 Mon Sep 17 00:00:00 2001 From: Onur Solmaz Date: Fri, 13 Mar 2026 08:02:56 +0100 Subject: [PATCH] fix(cli): teach bots to use external owner flags --- cli/skills/spz/SKILL.md | 24 +++++++++++++++---- cli/test/skillflag.test.ts | 2 ++ ...oner-and-service-principal-architecture.md | 9 ++++++- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/cli/skills/spz/SKILL.md b/cli/skills/spz/SKILL.md index 925c89b..4141b72 100644 --- a/cli/skills/spz/SKILL.md +++ b/cli/skills/spz/SKILL.md @@ -87,11 +87,15 @@ So if `spz profile current` returns a profile, assume Spritz is already configur ## Service-principal create flow -For external provisioners, the normal command is: +For bots and other external provisioners, prefer external owner resolution when +you only know the user's platform identity. + +Example for a Discord-triggered create: ```bash spz create \ - --owner-id user-123 \ + --owner-provider discord \ + --owner-subject 123456789012345678 \ --preset openclaw \ --idle-ttl 24h \ --ttl 168h \ @@ -103,7 +107,11 @@ spz create \ Rules: -- `owner-id` is the human who should own the workspace +- for Discord, Slack, Teams, and similar platform-triggered creates, pass the + external platform user through `--owner-provider` and `--owner-subject` +- never pass a Discord, Slack, or Teams user ID through `--owner-id` +- use `--owner-id` only when you already have the canonical internal Spritz + owner ID and intend a direct internal/admin create - the service principal is only the actor - the same `idempotency-key` and same request should replay the same workspace - the same `idempotency-key` with a different request should fail with conflict @@ -111,7 +119,13 @@ Rules: ## Common commands -Create from a preset: +Create from a preset for an external platform user: + +```bash +spz create --preset openclaw --owner-provider discord --owner-subject 123456789012345678 --idle-ttl 24h --ttl 168h --idempotency-key req-123 --json +``` + +Create from a preset for a known internal owner: ```bash spz create --preset openclaw --owner-id user-123 --idle-ttl 24h --ttl 168h --idempotency-key req-123 --json @@ -158,6 +172,8 @@ spz profile use staging - prefer `--preset` over `--image` when a preset exists - prefer bearer-token auth for bots +- for chat-platform-triggered creates, prefer external owner flags over direct + `--owner-id` - treat the create response as the source of truth for the access URL - do not construct workspace URLs yourself - use idempotency keys for any retried or externally triggered create operation diff --git a/cli/test/skillflag.test.ts b/cli/test/skillflag.test.ts index de1b77a..4d16741 100644 --- a/cli/test/skillflag.test.ts +++ b/cli/test/skillflag.test.ts @@ -39,4 +39,6 @@ test('skillflag show returns the bundled spz skill body', async () => { assert.equal(result.code, 0, result.stderr); assert.match(result.stdout, /# spz/); assert.match(result.stdout, /service-principal create flow/i); + assert.match(result.stdout, /--owner-provider discord/i); + assert.match(result.stdout, /never pass a Discord, Slack, or Teams user ID through `--owner-id`/i); }); diff --git a/docs/2026-03-11-external-provisioner-and-service-principal-architecture.md b/docs/2026-03-11-external-provisioner-and-service-principal-architecture.md index fdeb089..6ff1001 100644 --- a/docs/2026-03-11-external-provisioner-and-service-principal-architecture.md +++ b/docs/2026-03-11-external-provisioner-and-service-principal-architecture.md @@ -416,7 +416,8 @@ Examples: ```bash spz create \ - --owner-id user-123 \ + --owner-provider discord \ + --owner-subject 123456789012345678 \ --preset openclaw \ --idle-ttl 24h \ --ttl 168h \ @@ -430,11 +431,17 @@ spz suggest-name --preset openclaw --json The CLI should also support: +- `--owner-id` for direct internal/admin creates when the caller already knows + the canonical internal owner ID +- `--owner-provider` and `--owner-subject` for external platform identities - `--api-url` - `--token` - `--namespace` when allowed by policy - `--repo` and `--branch` only if the provisioner policy permits them +For chat-platform-triggered creates, external platform user IDs must not be +sent through `--owner-id`. + The CLI should not construct canonical URLs or infer authorization semantics on its own.