requestshield 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +414 -276
  2. package/config/.env.prod +7 -0
  3. package/package.json +8 -5
  4. package/skills/requestshield/SKILL.md +55 -63
  5. package/skills/requestshield/assets/AGENTS.codex.md +17 -17
  6. package/skills/requestshield/references/backend-java-core.md +3 -3
  7. package/skills/requestshield/references/backend-spring-boot.md +3 -3
  8. package/skills/requestshield/references/browser-manual.md +4 -4
  9. package/skills/requestshield/references/browser-seamless.md +7 -15
  10. package/skills/requestshield/references/cli.md +93 -169
  11. package/skills/requestshield/references/integration-planning.md +20 -47
  12. package/skills/requestshield/references/troubleshooting.md +26 -30
  13. package/src/api-client.mjs +106 -165
  14. package/src/args.mjs +108 -151
  15. package/src/browser-opener.mjs +32 -0
  16. package/src/cli.mjs +50 -28
  17. package/src/commands/agent-setup.mjs +34 -37
  18. package/src/commands/application-mutations.mjs +33 -0
  19. package/src/commands/application-response.mjs +55 -0
  20. package/src/commands/apps-get.mjs +3 -47
  21. package/src/commands/apps-list.mjs +40 -36
  22. package/src/commands/auth-status.mjs +37 -0
  23. package/src/commands/keys-create.mjs +7 -38
  24. package/src/commands/mutation-support.mjs +110 -0
  25. package/src/commands/secret-commands.mjs +45 -0
  26. package/src/commands/signin.mjs +70 -57
  27. package/src/commands/signout.mjs +9 -0
  28. package/src/commands/update-check.mjs +12 -4
  29. package/src/config.mjs +145 -3
  30. package/src/entrypoint.mjs +24 -0
  31. package/src/errors.mjs +3 -1
  32. package/src/main.mjs +2 -21
  33. package/src/oauth-client.mjs +153 -0
  34. package/src/oauth-loopback.mjs +120 -0
  35. package/src/session-files.mjs +213 -0
  36. package/src/session-store.mjs +177 -64
  37. package/src/commands/billing-get.mjs +0 -110
  38. package/src/commands/challenge-volume.mjs +0 -81
  39. package/src/commands/contract.mjs +0 -106
@@ -1,183 +1,107 @@
1
1
  # `requestshield` CLI reference
2
2
 
3
- Every RequestShield platform action goes through this CLI. There is no supported way
4
- to create keys, read the contract, or check traffic by hand-crafting HTTP calls, so if
5
- a task needs one of these values, run the command rather than guessing.
6
-
7
- Commands marked **auth** require a signed-in session (`requestshield signin`). The CLI
8
- also exposes local commands that do not need platform API access, such as `--help`,
9
- `--version`, and agent setup. Check once with `auth status` before a multi-step
10
- platform task instead of discovering it halfway through an edit.
11
-
12
- Most commands print JSON shaped `{"ok": true, "data": {...}}`. Parse `data`; treat
13
- `ok: false` as a hard stop and surface the message rather than continuing with edits.
14
-
15
- ## Contents
16
-
17
- - [General](#general)
18
- - [Authentication](#authentication)
19
- - [Key management](#key-management)
20
- - [Integration contract](#integration-contract)
21
- - [Applications](#applications)
22
- - [Credentials](#credentials)
23
- - [Service and monitoring](#service-and-monitoring)
24
- - [Billing](#billing)
25
- - [Agent integration](#agent-integration)
26
-
27
- ## General
28
-
29
- | Command | Purpose |
30
- | --- | --- |
31
- | `requestshield --help` | Usage and the full command list. Run this if a command below is rejected — the installed CLI may be older or newer than this file. |
32
- | `requestshield --version` | Installed CLI version, e.g. `requestshield 1.0.0`. |
33
- | `requestshield update check` | Latest available version. Use it when behaviour disagrees with this reference. |
34
-
35
- ## Authentication
36
-
37
- ```bash
38
- requestshield signin
39
- requestshield auth status
3
+ Check `requestshield --version` and `requestshield --help` against this guide.
4
+ An older published version may not contain these commands. Use the CLI for its
5
+ supported application and credential operations; do not invent endpoints for
6
+ unavailable commands.
7
+
8
+ ## Authentication and local commands
9
+
10
+ ```console
11
+ requestshield signin [--no-open]
12
+ requestshield auth status [--json]
13
+ requestshield signout
14
+ requestshield --help
15
+ requestshield --version
40
16
  ```
41
17
 
42
- **auth/API.**
43
-
44
- `signin` is interactive and stores a session on the machine. **Never try to automate
45
- it or ask for the user's credentials** if the user is signed out, tell them to run it
46
- themselves and wait.
47
-
48
- `auth status` returns `{"ok":true,"data":{"authenticated":true,"customer_id":"customer_456"}}`.
49
- The `customer_id` is useful context to echo back so the user can confirm they are
50
- operating on the right account before you create or deactivate anything.
51
-
52
- ## Key management
53
-
54
- **The user runs these, not you.** They print the API Secret or change state for a live
55
- App Key, so hand over the exact command and let them run it in their own terminal. See
56
- "Key and secret management" in `SKILL.md` for the hand-off and the follow-up
57
- presence check.
58
-
59
- ```bash
60
- requestshield keys create --app-name <name>
61
- requestshield keys deactive --app-key <app-key> # or --app-name <name>
62
- requestshield app key rotate --app-key <app-key> # or --app-name <name>
63
- ```
64
-
65
- `keys create` returns both halves:
66
-
67
- ```
68
- App Key: app_123
69
- Secret Key: rs_sk_xxxxx
70
- Save this Secret Key now. It will not be shown again.
71
- ```
72
-
73
- The Secret Key appears exactly once. Warn the user *before* they run the command that
74
- they need somewhere to put it, and afterwards point them at the environment variable
75
- rather than repeating the value. Never ask them to paste the secret back — confirm it
76
- only by presence. See the secret-handling rules in `SKILL.md`.
77
-
78
- `keys deactive` (spelled that way in the CLI) needs at least one of `--app-key` or
79
- `--app-name`; if both are given, `--app-key` wins. Deactivation stops traffic being
80
- verified for that key, so name the affected app explicitly when you hand the command
81
- over and make sure the user means that key.
82
-
83
- `app key rotate` issues a new Secret Key for an existing App Key and deactivates the
84
- previous one. This is the correct response to a leaked or lost secret — it keeps the
85
- App Key stable, so no browser or config change is needed beyond the new secret. Like
86
- `keys create`, the user runs it.
87
-
88
- ## Integration contract
89
-
90
- ```bash
91
- requestshield contract
92
- ```
93
-
94
- **auth.** The authoritative integration surface — run this before writing any
95
- integration code. The block below is an **illustration of the shape only**; never read
96
- values out of it, and in particular do not treat its `available_modes` as the modes your
97
- customer has:
98
-
99
- ```json
100
- {"ok":true,"data":{
101
- "contract_version":"2026-08-27",
102
- "browser":{"script_url":"https://.../intellifend.js","token_header":"X-IntelliFend-Token",
103
- "available_modes":["manual"]},
104
- "backend":{"supported_languages":["java"],"min_jdk":17},
105
- "release_state":"..."}}
106
- ```
107
-
108
- Use `script_url` and `token_header` verbatim. Check `available_modes` before committing
109
- to seamless or manual — a mode absent from that list is not released, and writing an
110
- integration against it produces code that will not work. Check `supported_languages`
111
- before promising a backend integration for a stack that is not listed; the browser side
112
- alone provides no protection, so an unsupported backend means the honest answer is
113
- "not yet supported here".
18
+ Sign-in uses the user's browser on the same computer. Let the user complete it;
19
+ never ask for their password, tokens or callback URL. `auth status --json` reads
20
+ local metadata only and does not contact the provider or refresh credentials.
21
+ It returns `profile`, `apiUrl`, `issuer`, `clientId`, `state`, `localOnly: true`
22
+ and applicable `expiresAt`/`scopes`, never tokens or a customer/account identity.
23
+ States are `signed_out`, `valid`, `expired`, `refresh_uncertain`, `config_mismatch`,
24
+ `invalid` and `configuration_error`. Local validity is not provider acceptance.
25
+ Sign-out removes only the selected local session, not the browser session or
26
+ provider grant.
114
27
 
115
28
  ## Applications
116
29
 
117
- ```bash
118
- requestshield apps list
30
+ ```console
31
+ requestshield apps list [--json] [--limit <1-100>] [--cursor <cursor> | --all]
119
32
  requestshield apps get <app-key>
33
+ requestshield apps rename <app-key> --name <name> [--idempotency-key <key>]
34
+ requestshield apps enable <app-key> [--idempotency-key <key>]
35
+ requestshield apps disable <app-key> [--idempotency-key <key>] [--yes]
120
36
  ```
121
37
 
122
- **auth.** `apps list` returns the applications the current user can access, each with
123
- `appKey`, `name`, `status`, `createdAt`, and `updatedAt`; JSON output also includes
124
- `nextCursor`. Use it to resolve a human-supplied app name to a key rather than asking
125
- the user to retype one.
126
-
127
- `apps get <app-key>` returns `app_key`, `name`, and `status`. Status distinguishes a
128
- key that has never seen traffic (`ready`) from one in normal service (`active`) — which
129
- is exactly the difference between "the integration is not wired up yet" and "it is
130
- working", so check it before spending time debugging code.
131
-
132
- ## Credentials
133
-
134
- ```bash
135
- requestshield credentials status <app-key>
136
- ```
137
-
138
- **auth.** Returns metadata only `provisioned`, `active`, `shared` and never the
139
- secret value. Use it to answer "is the secret configured?" without anyone having to
140
- paste a credential. A key that is `provisioned: false` explains backend failures far
141
- faster than reading code.
142
-
143
- ## Service and monitoring
144
-
145
- ```bash
146
- requestshield server
147
- requestshield challenge volume <app-key> [--from <time>] [--to <time>] [--granularity <value>]
148
- ```
149
-
150
- **auth.** `server` reports `healthy` or `degraded`. Check it first when an integration
151
- that was working starts behaving oddly — a degraded platform explains fail-open
152
- behaviour on the backend without anything being wrong in the customer's code.
153
-
154
- `challenge volume` is runtime evidence that the browser/platform half is active. It is
155
- not proof that the protected backend enforces a blocking decision; the controlled
156
- negative test in `SKILL.md` provides that evidence. Times are ISO-8601
157
- (`2026-08-01T00:00:00Z`); `--granularity` takes values such as `hour` or `day`. A
158
- `challenge_count` of zero after the user has exercised the endpoint means the browser
159
- half is not firing — that is a browser-side bug, not a backend one, so start with the
160
- mode's reference file.
161
-
162
- ## Billing
163
-
164
- ```bash
165
- requestshield get billing <app-key>
38
+ These commands require sign-in. Existing-app commands use exact App Keys; names
39
+ are not unique. List defaults to one page. `--all` follows at most 100 pages and
40
+ fails for repeated cursors or unfinished traversal at that bound. It cannot be
41
+ combined with `--cursor`. For name discovery, inspect all necessary pages and
42
+ resolve ambiguity with the user before choosing an App Key.
43
+
44
+ JSON list output is `{data:Application[],nextCursor}`. Detail and rename output
45
+ is `{data:Application}`. Application has exactly `appKey`, `name`, `status`,
46
+ `createdAt`, `updatedAt`. Status is `pending`, `enabled`, `disabled`, `revoked`
47
+ or `attention_required`; it describes configuration, not traffic or enforcement.
48
+ Pending, attention and disabled states do not expose the exact credential state.
49
+ Disable retains the secret; enable requires an active one.
50
+
51
+ ## Key and secret management
52
+
53
+ Have the user run commands that print secrets in their own terminal so secret
54
+ values stay out of tool output and transcripts. Give the exact command and
55
+ confirm storage by presence only.
56
+
57
+ ```console
58
+ requestshield keys create --app-name <name> [--idempotency-key <key>]
59
+ requestshield keys rotate <app-key> [--idempotency-key <key>] [--yes]
60
+ requestshield keys reveal <app-key> [--yes]
61
+ requestshield keys revoke <app-key> [--idempotency-key <key>] [--yes]
166
62
  ```
167
63
 
168
- **auth.** Current plan and usage for the explicitly selected application. Read-only;
169
- surface it when the user asks about cost or limits.
170
-
171
- ## Agent integration
172
-
173
- ```bash
174
- requestshield agent setup
175
- requestshield agent setup --agent claude
176
- requestshield agent setup --agent codex
64
+ Create makes a new application and initial secret. Rotate preserves the App Key
65
+ and replaces the secret. Reveal retrieves the current active secret; use it to
66
+ recover a lost issuance response. Exposure requires rotation, not reveal.
67
+ Revoke invalidates the current secret. Create, rotate and reveal can display an
68
+ API secret; the CLI never persists it. Store it in backend secret storage.
69
+
70
+ Create, rename and enable have no prompt. Disable, rotate, revoke and reveal
71
+ require confirmation; `--yes` skips it. These commands can change live state or
72
+ disclose secrets, so ensure the target and action match the user's request.
73
+
74
+ All mutations except reveal accept an idempotency key. A fresh key is generated
75
+ per invocation when omitted and printed to stderr before dispatch so interrupted
76
+ commands can reuse it; JSON stdout is unchanged. There is no automatic mutation retry. On uncertainty,
77
+ repeat the identical request and key printed in the error within seven days.
78
+ A new key is a new operation. After seven days inspect state before acting.
79
+ Create/rotate replay can have `apiSecret: null`; the CLI directs explicit reveal
80
+ without running it. HTTP 202 and `enabled` do not prove global propagation.
81
+
82
+ ## Agent setup and updates
83
+
84
+ ```console
85
+ requestshield agent setup [--codex | --claude] [--force]
86
+ requestshield update check
177
87
  ```
178
88
 
179
- Local setup. Installs this skill for the named agent. With no `--agent`, the CLI detects
180
- which agent is in use. Run it when the user wants the skill available in another repo or
181
- for the other agent; it is the supported alternative to copying files by hand. It should
182
- not require a RequestShield App Key or API Secret, and it must not create, rotate, or
183
- deactivate customer credentials.
89
+ Agent setup copies the skill to `~/.agents/skills/requestshield` for Codex or
90
+ `~/.claude/skills/requestshield` for Claude. With neither flag, it detects the
91
+ agent or asks if both are available. `--force` replaces an existing installation.
92
+ It does not edit repository `AGENTS.md` or customer application code.
93
+
94
+ Production update check queries npm and asks before a global installation.
95
+ Explain that target before accepting an update; it does not update a pinned
96
+ invocation or source checkout. Repository-only QAT/STG runners return local
97
+ source-update guidance without registry access or installation.
98
+
99
+ ## Unavailable commands
100
+
101
+ Integration contract, service health, credential-status metadata, challenge
102
+ volume and billing are not implemented CLI capabilities. `contract`,
103
+ `challenge volume` and `get billing` fail with `COMMAND_UNAVAILABLE` before
104
+ configuration, authentication or network access. `server` and
105
+ `credentials status` are unsupported. Use the published SDK documentation for
106
+ the chosen release and safe browser/backend observations for integration checks.
107
+ Do not infer traffic or enforcement from `apps get` status.
@@ -71,12 +71,10 @@ Common variable names are `INTELLIFEND_REQUESTSHIELD_APP_KEY`,
71
71
  Confirm that the backend actually reads or maps that variable before treating it as a
72
72
  valid RequestShield credential.
73
73
 
74
- If the App Key is known, also confirm server-side credential state without exposing the
75
- secret:
76
-
77
- ```bash
78
- requestshield credentials status <app-key>
79
- ```
74
+ If the App Key is known, inspect its aggregate application configuration with
75
+ `requestshield apps get <app-key>`. That status does not prove the exact credential
76
+ state or that the deployed backend has received its secret. The CLI has no separate
77
+ credential-status command; check runtime injection by presence only.
80
78
 
81
79
  A credential that is not present in the current shell is not necessarily missing from
82
80
  the deployed backend. It may be injected at runtime by a secret manager, CI/CD system,
@@ -182,47 +180,22 @@ last one to run wins rather than the two merging.
182
180
 
183
181
  ## Contract check
184
182
 
185
- Run this **after** detection and **before** the Gate: detection says what the codebase
186
- already does, the contract says what the platform currently allows, and the browser-mode
187
- decision needs both.
188
-
189
- ```bash
190
- requestshield contract
191
- ```
192
-
193
- It is authoritative for `browser.script_url`, `browser.token_header`,
194
- `browser.available_modes`, `backend.supported_languages`, and `backend.min_jdk`. Use
195
- those values verbatim; a stale hardcoded script URL produces a page that loads nothing
196
- and fails silently.
197
-
198
- Treat every array as an **allow-list**. There is no "unavailable" flag, so something is
199
- unavailable when it is absent and an absent, empty, or unparseable array is
200
- unavailable, not permission. If the contract is missing or returns `ok: false`, stop and
201
- report what the CLI returned.
202
-
203
- ### Backend consequences — these feed the Gate
204
-
205
- - `backend.supported_languages` missing the customer's backend language → **stop.** No
206
- backend path exists, and a browser-only install protects nothing.
207
- - `backend.min_jdk` above the project's Java target → **stop.** The JDK upgrade is the
208
- prerequisite; do not fall back to an older SDK version.
209
-
210
- ### Browser-mode consequences — these decide the mode
211
-
212
- Read `browser.available_modes` together with what detection found in the codebase:
213
-
214
- | Released modes | Codebase today | Do this |
215
- | --- | --- | --- |
216
- | **One mode** | already uses that mode | Keep it. Nothing to change on the browser side. |
217
- | **One mode** | uses the *other* mode | **This is a finding, not a preference.** The mode in the codebase is not released, so it cannot be relied on. Report it and migrate the client to the released mode. |
218
- | **One mode** | not integrated | No choice to make. Install that mode, and say which one and why. |
219
- | **Both modes** | already uses one of them | **Keep the mode already in use.** Change it only for a concrete reason — the transport is one Seamless cannot cover, or the user asks. A mode switch rewrites working call sites and risks leaving an endpoint half-migrated. |
220
- | **Both modes** | not integrated | A genuine choice. Go to **Choosing the mode** below. |
221
- | **Neither** | any | **Stop.** No browser mode is released; report the contract output. |
222
-
223
- Per-endpoint, not per-repo: a page may legitimately run Seamless on one endpoint and
224
- Manual on another. Apply the table to the operation being worked on, not to the codebase
225
- as a whole.
183
+ After detecting the current integration, consult the customer Browser SDK and Java
184
+ SDK documentation for the selected release. Confirm the script URL, token header,
185
+ supported browser modes, backend languages and minimum Java version before editing.
186
+ The CLI integration-contract command is unavailable; do not require it as a preflight
187
+ or fabricate its output.
188
+
189
+ The documented backend paths here require Java 17 or newer. The Spring Boot starter
190
+ also requires Spring Boot 3 with Spring MVC; Java core is a separate supported path.
191
+ Do not promise support for another backend language without its release documentation.
192
+ A browser-only installation does not enforce protection.
193
+
194
+ Select a browser mode supported by the selected release and the request transport.
195
+ Keep an existing supported mode unless the transport requires a change or the user
196
+ requests one. If release documentation is missing, resolve that evidence before
197
+ making the dependent integration change. A page may use different modes for different
198
+ operations, but each operation uses exactly one mode.
226
199
 
227
200
  ## Gate
228
201
 
@@ -4,23 +4,22 @@ Work outward from the request, not from the code. Most reports of "RequestShield
4
4
  broken" are one of four things: the browser never attached a token, CORS stripped the
5
5
  header, the backend never verified it, or one token was verified twice.
6
6
 
7
- ## First three checks
7
+ ## First checks
8
8
 
9
- ```bash
10
- requestshield server # platform healthy or degraded?
11
- requestshield apps get <app-key> # status: ready (no traffic yet) or active?
12
- requestshield credentials status <app-key> # provisioned and active?
9
+ ```console
10
+ requestshield auth status --json
11
+ requestshield apps get <app-key>
13
12
  ```
14
13
 
15
- `status: ready` means the platform has never seen traffic for that key — the integration
16
- is not wired up yet, so debugging backend enforcement logic is premature. Start at the
17
- browser.
14
+ Session status is local only. Application status is configuration state, not
15
+ traffic: `pending`, `enabled`, `disabled`, `revoked` or `attention_required`.
16
+ It cannot prove that the browser sent a request or that a deployed backend has the
17
+ current secret. Inspect browser requests and safe backend decision metrics separately.
18
+ The CLI has no service-health or credential-status command.
18
19
 
19
- Run `credentials status` even when the pre-edit Credentials check in
20
- `integration-planning.md` passed during the install. That check greps the **local
21
- shell**; it says nothing about what the deployed backend actually receives, and a secret
22
- can be rotated, or missed by the deploy environment, after it passed. This is the check
23
- that answers `consume_unauthorized`.
20
+ Confirm runtime secret injection by presence only. A secret absent from the current
21
+ shell may still be supplied by the deployed environment; a rotated secret may not
22
+ have reached that backend yet. Never read or print the value to diagnose this.
24
23
 
25
24
  ## Reason codes
26
25
 
@@ -40,10 +39,10 @@ name.
40
39
  | `token_tampered` | Token failed integrity checks | Something modified the value in transit — a proxy rewriting headers, or application code trimming or re-encoding it. Pass the value through unchanged. |
41
40
  | `token_expired` | Token too old | The page held a token instead of obtaining a fresh one per request, or a very slow round trip. |
42
41
  | `token_replayed` | Already consumed | The same token verified twice: a retry reusing the first token, or two verification paths on one request (`@RequestShieldProtected` plus a manual `verify()`, or a filter plus a controller). |
43
- | `consume_unauthorized` | Backend credentials rejected | API Secret wrong, rotated, or not injected — check `credentials status` and the environment variable. |
42
+ | `consume_unauthorized` | Backend credentials rejected | API Secret wrong, rotated, or not injected — confirm runtime secret injection and recent rotations without reading the value. |
44
43
  | `invalid_request` | Malformed verification request | Usually a mis-set `challenge-server-url`. |
45
44
  | `not_found` | Token unknown to the platform | Cross-environment mismatch — a staging page's token verified against production, or the reverse. |
46
- | `service_unavailable` | Platform unreachable | Check `requestshield server`. See degraded behaviour below. |
45
+ | `service_unavailable` | Platform unreachable | Check backend connectivity and safe health metrics. See degraded behaviour below. |
47
46
 
48
47
  ## "It blocks everything"
49
48
 
@@ -61,7 +60,7 @@ cheap and rules out a whole class:
61
60
  strips it before it ever leaves.
62
61
  4. **Header present but empty** → the SDK ran and could not obtain a token. Check the CSP
63
62
  includes `worker-src 'self' blob:` and that `connect-src` allows the challenge host,
64
- then check `requestshield server`. (In Manual mode an empty token means the header
63
+ then check connectivity and safe backend health observations. (In Manual mode an empty token means the header
65
64
  should be omitted, not sent empty — see `browser-manual.md`.)
66
65
  5. **Header present and populated** → backend half. Compare the App Key on both sides
67
66
  character for character, then confirm the secret is actually injected at runtime.
@@ -89,20 +88,16 @@ platform outage cannot take down a customer's checkout flow.
89
88
 
90
89
  Communicate the consequence clearly: during a degraded window, traffic passes without
91
90
  real verification. Log the degraded rate as its own metric so it is visible, and check
92
- `requestshield server` when it rises. Never "fix" a degraded result by overriding
91
+ backend connectivity and service health through established monitoring when it rises. Never "fix" a degraded result by overriding
93
92
  `isAllowed()` — that converts a platform incident into a customer-facing outage.
94
93
 
95
- ## Confirming traffic reaches the platform
96
-
97
- ```bash
98
- requestshield challenge volume <app-key> --from 2026-08-01T00:00:00Z \
99
- --to 2026-08-27T23:59:59Z --granularity day
100
- ```
94
+ ## Confirming traffic and enforcement
101
95
 
102
- Challenge volume is runtime evidence that the browser/platform half is active. It does
103
- not prove that the backend enforces a blocking decision. Report static correctness,
104
- platform traffic, and backend enforcement separately. Use the controlled negative test
105
- in `SKILL.md` to prove enforcement.
96
+ Use browser network observations and existing safe backend metrics in an authorized
97
+ environment. Do not record raw tokens or secrets. CLI challenge-volume analytics are
98
+ unavailable; application status is not a traffic measurement. Report static correctness,
99
+ observed requests and backend enforcement separately. Use the controlled negative
100
+ test in `SKILL.md` to demonstrate enforcement.
106
101
 
107
102
  ## Secret exposure
108
103
 
@@ -110,9 +105,10 @@ If the API Secret appears in a repo, a log, a build artifact, or a chat transcri
110
105
  rotate it — deleting the line does not un-expose it:
111
106
 
112
107
  ```bash
113
- requestshield app key rotate --app-key <app-key>
108
+ requestshield keys rotate <app-key>
114
109
  ```
115
110
 
116
111
  The App Key is unchanged, so no browser edit is needed. Deploy the new secret to backend
117
- secret storage; the previous one is deactivated automatically. Warn the user that the new
118
- secret is displayed once.
112
+ secret storage. Rotation replaces the previous secret, but publication is asynchronous.
113
+ Warn the user that the new secret is displayed and must stay out of transcripts. A lost
114
+ response can be recovered with explicit reveal; an exposed secret requires rotation.