requestshield 0.0.0-stage → 1.0.0-stg.276
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.
- package/README.md +292 -2
- package/config/.env.stg +8 -0
- package/package.json +25 -4
- package/skills/requestshield/SKILL.md +240 -0
- package/skills/requestshield/assets/AGENTS.codex.md +107 -0
- package/skills/requestshield/references/backend-java-core.md +152 -0
- package/skills/requestshield/references/backend-spring-boot.md +158 -0
- package/skills/requestshield/references/browser-manual.md +244 -0
- package/skills/requestshield/references/browser-seamless.md +213 -0
- package/skills/requestshield/references/cli.md +314 -0
- package/skills/requestshield/references/integration-planning.md +357 -0
- package/skills/requestshield/references/troubleshooting.md +131 -0
- package/src/agent-detector.mjs +102 -0
- package/src/api-client.mjs +155 -0
- package/src/args.mjs +147 -0
- package/src/browser-opener.mjs +32 -0
- package/src/cli.mjs +115 -0
- package/src/command-completion.mjs +10 -0
- package/src/command-registry.mjs +151 -0
- package/src/commands/agent-setup.mjs +195 -0
- package/src/commands/agent-status.mjs +65 -0
- package/src/commands/application-mutations.mjs +37 -0
- package/src/commands/application-response.mjs +55 -0
- package/src/commands/apps-get.mjs +28 -0
- package/src/commands/apps-list.mjs +93 -0
- package/src/commands/auth-status.mjs +42 -0
- package/src/commands/billing.mjs +106 -0
- package/src/commands/contract.mjs +59 -0
- package/src/commands/keys-create.mjs +22 -0
- package/src/commands/mutation-support.mjs +135 -0
- package/src/commands/output.mjs +26 -0
- package/src/commands/secret-commands.mjs +66 -0
- package/src/commands/secret-output.mjs +52 -0
- package/src/commands/service-status.mjs +34 -0
- package/src/commands/signin.mjs +95 -0
- package/src/commands/signout.mjs +14 -0
- package/src/commands/update-check.mjs +205 -0
- package/src/commands/usage.mjs +72 -0
- package/src/config.mjs +200 -0
- package/src/entrypoint.mjs +44 -0
- package/src/errors.mjs +16 -0
- package/src/integration-contract-client.mjs +85 -0
- package/src/integration-contract.mjs +114 -0
- package/src/main.mjs +6 -0
- package/src/oauth-client.mjs +153 -0
- package/src/oauth-loopback.mjs +120 -0
- package/src/package-profile.mjs +24 -0
- package/src/private-path.mjs +33 -0
- package/src/secret-output.mjs +121 -0
- package/src/service-status-client.mjs +87 -0
- package/src/session-files.mjs +192 -0
- package/src/session-store.mjs +204 -0
- package/src/terminal.mjs +143 -0
- package/src/usage-time.mjs +26 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# Integration planning
|
|
2
|
+
|
|
3
|
+
Use this reference for sign-in when required by the calling workflow and before
|
|
4
|
+
writing or removing RequestShield integration code. It owns the planning steps that
|
|
5
|
+
are too detailed for `SKILL.md`.
|
|
6
|
+
|
|
7
|
+
## Workflow by operation
|
|
8
|
+
|
|
9
|
+
Follow [SKILL.md — Classify the request](../SKILL.md#classify-the-request).
|
|
10
|
+
Use only the planning steps required by that intent.
|
|
11
|
+
|
|
12
|
+
## Sign-in
|
|
13
|
+
|
|
14
|
+
1. Run `requestshield auth status --json`. Status confirms the local session,
|
|
15
|
+
not online access.
|
|
16
|
+
- `valid`: return to the calling workflow; no new login is needed.
|
|
17
|
+
- `expired`: return to the calling workflow. The next authenticated command
|
|
18
|
+
attempts refresh automatically; expiry alone does not require browser sign-in.
|
|
19
|
+
Preserve that workflow's confirmation requirements before running its command.
|
|
20
|
+
- `configuration_error`: report the configuration failure and stop the dependent
|
|
21
|
+
action; browser sign-in does not fix CLI configuration.
|
|
22
|
+
- `signed_out`, `refresh_uncertain`, `config_mismatch`, or `invalid`: continue
|
|
23
|
+
with browser sign-in below.
|
|
24
|
+
If status fails or reports an unknown state, report the failure and follow the
|
|
25
|
+
CLI's recovery guidance rather than assuming login is required.
|
|
26
|
+
2. When browser sign-in is required, explain that the CLI will start sign-in while the user completes the
|
|
27
|
+
browser flow. Ask for fresh confirmation through the host's interactive question
|
|
28
|
+
tool with **Yes** and **No**. Wait for an explicit **Yes**. If no permitted tool is
|
|
29
|
+
available, pause this step. Silence or a preselected option is not approval.
|
|
30
|
+
3. Run `requestshield login` in an interactive PTY and keep it alive while the user
|
|
31
|
+
completes authentication in the browser. If an interactive PTY is unavailable,
|
|
32
|
+
ask the user to run `requestshield login` in their own terminal. Do not emulate
|
|
33
|
+
login or call authentication APIs manually.
|
|
34
|
+
4. After login completes, run `requestshield auth status --json` again. Continue the
|
|
35
|
+
calling workflow only when it reports `state: "valid"`. Otherwise report the
|
|
36
|
+
failure and stop the dependent action. A browser launch, redirect, or user
|
|
37
|
+
confirmation alone does not establish sign-in.
|
|
38
|
+
|
|
39
|
+
If the calling workflow's authenticated command fails, follow the CLI's recovery
|
|
40
|
+
guidance. A sign-in-required error returns to step 2. A retryable refresh failure
|
|
41
|
+
(such as `SESSION_REFRESH_FAILED`) does not itself require browser sign-in; report
|
|
42
|
+
the failure and preserve the command's retry rules. Never blindly retry a mutation
|
|
43
|
+
whose result is uncertain; use the existing idempotent-retry guidance in
|
|
44
|
+
[the CLI reference](cli.md#key-and-secret-management).
|
|
45
|
+
|
|
46
|
+
Never request, read, copy, or enter passwords, passkeys, MFA codes, authentication
|
|
47
|
+
tokens, sign-in URLs, or callback URLs on the user's behalf.
|
|
48
|
+
|
|
49
|
+
## Discover and select protected endpoints
|
|
50
|
+
|
|
51
|
+
This is the first Install planning step unless the user already supplied an explicit,
|
|
52
|
+
intentionally narrow set of exact HTTP method/path pairs. Discovery is read-only and
|
|
53
|
+
does not authorize integration changes.
|
|
54
|
+
|
|
55
|
+
### Build the candidate inventory
|
|
56
|
+
|
|
57
|
+
Scan application source, excluding generated, vendored, dependency, fixture, and build
|
|
58
|
+
files. Find externally reachable browser operations that mutate state, authenticate,
|
|
59
|
+
expose abuse-sensitive capabilities, or trigger meaningful cost. Inspect browser call
|
|
60
|
+
sites, backend routes/handlers, actual effects, and existing protection.
|
|
61
|
+
|
|
62
|
+
Use focused framework-appropriate searches, starting with filenames. For example:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
rg -l "fetch\(|axios\.|XMLHttpRequest|\.request\(|<form|action=" \
|
|
66
|
+
-g "*.html" -g "*.js" -g "*.jsx" -g "*.ts" -g "*.tsx" \
|
|
67
|
+
-g "*.vue" -g "*.svelte" -g "!node_modules/**" -g "!**/build/**" .
|
|
68
|
+
|
|
69
|
+
rg -l "@(Post|Put|Patch|Delete|Request)Mapping|@(POST|PUT|PATCH|DELETE)|RouterFunctions|route\(" \
|
|
70
|
+
-g "*.java" -g "*.kt" -g "!**/build/**" -g "!**/target/**" .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Resolve base URLs, route prefixes, parameters, and HTTP verbs to the exact method/path
|
|
74
|
+
sent by the browser. Pair each operation with its browser call site and backend handler.
|
|
75
|
+
Mark unresolved ownership or missing pairs **Needs clarification**, not install-ready.
|
|
76
|
+
Inspect relevant logic using the redaction rules in **Detect existing integration**;
|
|
77
|
+
never dump configuration or secret files.
|
|
78
|
+
|
|
79
|
+
Exclude health/metrics, static reads, internal jobs, and non-browser operations that
|
|
80
|
+
cannot receive a browser token. Judge actual behavior: an expensive GET may need
|
|
81
|
+
protection, while a POST is not automatically sensitive.
|
|
82
|
+
|
|
83
|
+
### Rank candidates
|
|
84
|
+
|
|
85
|
+
Rank install-ready candidates using these factors in order:
|
|
86
|
+
|
|
87
|
+
1. Business/security impact: account recovery, payments, privilege changes, destruction.
|
|
88
|
+
2. Automation attractiveness: sign-in, registration, resets, checkout, submissions.
|
|
89
|
+
3. Exposure and existing controls: public operations without equivalent protection.
|
|
90
|
+
4. Operational cost and volume: messages, paid services, scarce resources, amplification.
|
|
91
|
+
5. Trace confidence and supportability: exact browser/handler pairs and supported transport.
|
|
92
|
+
|
|
93
|
+
Use `Critical`, `High`, `Medium`, or `Low` with a concrete reason, not an invented
|
|
94
|
+
numeric score. Mark complete integrations **Already protected**; partial integrations
|
|
95
|
+
remain selectable and must identify the missing half.
|
|
96
|
+
|
|
97
|
+
### Present a multi-select and wait
|
|
98
|
+
|
|
99
|
+
Present all actionable candidates using
|
|
100
|
+
[Interactive questions](../SKILL.md#interactive-questions). Each option shows priority,
|
|
101
|
+
exact HTTP method/path, reason, and current RequestShield state. Keep browser call-site
|
|
102
|
+
and backend-handler details available when useful. For Uninstall, omit priority and
|
|
103
|
+
use the protected-operation inventory specified in the skill.
|
|
104
|
+
|
|
105
|
+
Wait for the submitted selection, preserve its exact method/path set, and edit only
|
|
106
|
+
selected operations. Use the skill's Yes/No fallback when multi-select is unavailable.
|
|
107
|
+
|
|
108
|
+
### Process the selected set
|
|
109
|
+
|
|
110
|
+
Apply the remaining planning and installation steps from `SKILL.md` to each selected
|
|
111
|
+
operation. Reuse contract metadata, scripts, and configuration only for compatible
|
|
112
|
+
operations in the same application; never combine evidence from different owners.
|
|
113
|
+
Group mode questions only when transport, backend owner, capabilities, and intended
|
|
114
|
+
choice match.
|
|
115
|
+
|
|
116
|
+
Add missing protection, repair only missing halves, and preserve complete integrations
|
|
117
|
+
without duplicate scripts or verification paths. Validate every selected operation.
|
|
118
|
+
Report unselected recommendations as opportunities, not incomplete authorized work.
|
|
119
|
+
|
|
120
|
+
## Detect existing integration
|
|
121
|
+
|
|
122
|
+
Record each SDK's version and API separately from Seamless/Manual modes.
|
|
123
|
+
Preserve existing pins, API choices, credentials, and service base URLs.
|
|
124
|
+
Browser/Java 1.0.0 integrations use v1; newer documentation does not change
|
|
125
|
+
their browser, CSP, or Java requirements.
|
|
126
|
+
|
|
127
|
+
| SDK | API version |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| Browser 1.0.0 | v1, without an API-version option. |
|
|
130
|
+
| Browser 2.0.0 | v2 by default; `apiVersion: 'v1' \| 'v2'` or `data-api-version` selects it. |
|
|
131
|
+
| Java 1.0.0 | v1, without an API-version option. |
|
|
132
|
+
| Java 2.0.0 core and Spring Boot starter | v2 only; no builder or Spring API-version option. |
|
|
133
|
+
|
|
134
|
+
For new integrations, prefer matching browser and backend API versions. Mixed
|
|
135
|
+
versions can verify compatible tokens, and a token remains single-use across
|
|
136
|
+
both APIs. Backend availability checks observe only the API used by its SDK.
|
|
137
|
+
If the browser's other API cannot issue a token while the backend's API is
|
|
138
|
+
healthy, the backend can reject with `missing_token`. Check this behavior when
|
|
139
|
+
validating a mixed-version integration. Do not verify a token twice or add
|
|
140
|
+
automatic fallback from v2 to v1. Both APIs are available to active App Keys;
|
|
141
|
+
selecting v2 does not prevent another caller from obtaining a v1 challenge.
|
|
142
|
+
|
|
143
|
+
Search for existing RequestShield code before install, verify/troubleshoot, or uninstall. Use `rg` when available. Use `rg -l` for filename-only discovery.
|
|
144
|
+
|
|
145
|
+
Browser markers:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
rg -l "data-app-key|data-protect|IntelliFend|X-IntelliFend-Token" \
|
|
149
|
+
-g "*.html" -g "*.htm" -g "*.js" -g "*.jsx" -g "*.ts" -g "*.tsx" \
|
|
150
|
+
-g "*.vue" -g "*.svelte" -g "*.astro" \
|
|
151
|
+
-g "*.erb" -g "*.haml" -g "*.php" -g "*.jinja*" -g "*.j2" -g "*.twig" \
|
|
152
|
+
-g "*.hbs" -g "*.ejs" -g "*.pug" -g "*.blade.php" \
|
|
153
|
+
-g "!node_modules/**" -g "!**/skills/requestshield/**" -g "!**/.requestshield/**" .
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Include server-rendered layouts and any template extensions used by the application;
|
|
157
|
+
a scan limited to `.html`/`.js` can miss an existing SDK tag.
|
|
158
|
+
|
|
159
|
+
Backend markers:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
rg -l "RequestShieldClient|RequestShieldProtected|intellifend|requestshield" \
|
|
163
|
+
-g "*.java" -g "*.kt" -g "*.xml" -g "*.yml" -g "*.yaml" -g "*.properties" \
|
|
164
|
+
-g "*.gradle" -g "*.gradle.kts" \
|
|
165
|
+
-g "!**/skills/requestshield/**" -g "!**/.requestshield/**" .
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Inspect marker locations without exposing surrounding values:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
rg -n -o \
|
|
172
|
+
"data-app-key|data-protect|IntelliFend|getToken|X-IntelliFend-Token" \
|
|
173
|
+
<browser-candidate-file>
|
|
174
|
+
|
|
175
|
+
rg -n -o \
|
|
176
|
+
"RequestShieldClient|RequestShieldProtected|verify|isAllowed|intellifend|requestshield" \
|
|
177
|
+
<backend-candidate-file>
|
|
178
|
+
|
|
179
|
+
rg -n -o \
|
|
180
|
+
"(INTELLIFEND_)?REQUESTSHIELD_(APP_KEY|KEY|API_SECRET|SECRET)" \
|
|
181
|
+
<candidate-configuration-file>
|
|
182
|
+
```
|
|
183
|
+
`-o` returns only marker or variable names. For context, use a secret-aware parser or
|
|
184
|
+
redacted view before output reaches the agent. Allow filenames, line numbers, config
|
|
185
|
+
keys, variable names, public App Keys when needed, and reference/literal classification.
|
|
186
|
+
Mask API Secrets, tokens, sessions, CSRF, authorization values, and other credentials.
|
|
187
|
+
Never follow filename discovery with unredacted `cat`, `sed`, full matching lines, or
|
|
188
|
+
configuration dumps. If safe inspection is unavailable, request a sanitized excerpt.
|
|
189
|
+
Exclude installed skill/reference directories so their examples do not count as an
|
|
190
|
+
application integration.
|
|
191
|
+
|
|
192
|
+
Report one of:
|
|
193
|
+
|
|
194
|
+
- **Not integrated**: no browser or backend markers.
|
|
195
|
+
- **Browser only**: tokens may be obtained or attached, but no backend enforcement was
|
|
196
|
+
found. This looks protected and is not.
|
|
197
|
+
- **Backend only**: enforcement exists, but no page sends a token. In BLOCK mode this can
|
|
198
|
+
reject legitimate users.
|
|
199
|
+
- **Fully integrated**: frontend and backend integration modes are both present. Name
|
|
200
|
+
both, including the backend mechanism. A supported mixed pair is fully integrated;
|
|
201
|
+
it does not require migration merely to make the mode names match.
|
|
202
|
+
|
|
203
|
+
Update an existing SDK tag rather than adding another: configuration from
|
|
204
|
+
`document.currentScript` is replaced, not merged, by a second tag.
|
|
205
|
+
|
|
206
|
+
## Contract check
|
|
207
|
+
|
|
208
|
+
Run `requestshield contract --json` with the runner for the intended environment.
|
|
209
|
+
It requires no login. Use the returned URLs unchanged; never derive a versioned URL.
|
|
210
|
+
Confirm:
|
|
211
|
+
|
|
212
|
+
- Browser: `scriptUrlVersion`, `scriptUrlLatest`, matching integrity, `tokenHeader`,
|
|
213
|
+
`availableModes`, `cspAdditions`, and `sdkVersion` under `data.browser`.
|
|
214
|
+
- Service: `services.challengeUrl`.
|
|
215
|
+
- Backend: `sdkVersion`, `minJdk`, `mavenRepository`, `core`, and `springBoot3` coordinates.
|
|
216
|
+
- The three release documentation links.
|
|
217
|
+
|
|
218
|
+
Stop if the command or manifest is unavailable; do not fabricate values or substitute
|
|
219
|
+
an environment/release. Pinned browser metadata describes `scriptUrlVersion`, not
|
|
220
|
+
`scriptUrlLatest`. Use documentation for the selected release; never apply 2.x guidance
|
|
221
|
+
to a pinned 1.x release or infer latest capabilities from pinned metadata.
|
|
222
|
+
|
|
223
|
+
`browser.availableModes` describes frontend modes only. Establish backend capabilities
|
|
224
|
+
from SDK coordinates, release documentation, and the application stack. Preserve the
|
|
225
|
+
contract's JSON fields and apply mode preferences under **Choosing the modes**.
|
|
226
|
+
|
|
227
|
+
For a new Install without a selected supported URL, ask for `scriptUrlVersion` or
|
|
228
|
+
`scriptUrlLatest` using **Interactive questions** in `SKILL.md`. Preserve an existing
|
|
229
|
+
supported URL unless the user requests a change or the contract requires correction.
|
|
230
|
+
Do not query applications or credentials for this choice.
|
|
231
|
+
|
|
232
|
+
Use the chosen URL unchanged. Attach the contract's versioned integrity only to that
|
|
233
|
+
immutable URL; `latest` requires its own matching digest if SRI is used.
|
|
234
|
+
|
|
235
|
+
## Gate
|
|
236
|
+
|
|
237
|
+
Establish capabilities before editing; choose modes afterwards under **Choosing the
|
|
238
|
+
modes**. A non-Spring-MVC backend limits backend Seamless, not frontend Seamless.
|
|
239
|
+
|
|
240
|
+
| Layer / mode | Requirement | Reference |
|
|
241
|
+
| --- | --- | --- |
|
|
242
|
+
| Backend Seamless | Spring Boot 3 MVC, Java 17+, released starter | `backend-spring-boot.md` |
|
|
243
|
+
| Backend Manual | Java 17+, released core SDK, application extraction/enforcement; also works on Boot 3 MVC | `backend-java-core.md` |
|
|
244
|
+
| Frontend Seamless | Released support and page-scope `fetch` / async XHR interception | `browser-seamless.md` |
|
|
245
|
+
| Frontend Manual | Released token acquisition and supported application-controlled carrier | `browser-manual.md` |
|
|
246
|
+
|
|
247
|
+
Both backend modes accept `X-IntelliFend-Token`; a documented body carrier requires
|
|
248
|
+
backend Manual extraction. Manual mode does not make unsupported transport valid.
|
|
249
|
+
Check the selected browser reference's coverage and carrier requirements.
|
|
250
|
+
|
|
251
|
+
### Run the check
|
|
252
|
+
|
|
253
|
+
Locate the route's owning module, then inspect its build file. Repo-wide discovery
|
|
254
|
+
may find candidates, but never combine a route from one module with Java/Spring evidence
|
|
255
|
+
from another. If multiple services could own the endpoint, ask which one before editing.
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
rg --files -g 'pom.xml' -g 'build.gradle*' -g '!**/node_modules/**' \
|
|
259
|
+
-g '!**/build/**' -g '!**/target/**'
|
|
260
|
+
rg -n "/api/register" -g "*.java" -g "*.kt" .
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Java target version
|
|
264
|
+
|
|
265
|
+
Read the project's target, not the machine's JDK:
|
|
266
|
+
|
|
267
|
+
- Maven: `maven.compiler.release`, compiler-plugin `<release>`, or inherited
|
|
268
|
+
Spring Boot `<java.version>`; inspect the parent POM where needed.
|
|
269
|
+
- Gradle: `java.toolchain.languageVersion`, `sourceCompatibility`, or Kotlin
|
|
270
|
+
`jvmToolchain`, including nested configuration blocks.
|
|
271
|
+
- `.java-version`, `.sdkmanrc`, `.tool-versions`, CI JDK settings, and Docker base
|
|
272
|
+
images are hints only. If build evidence is missing, ask; `java -version` does not
|
|
273
|
+
establish the project's target.
|
|
274
|
+
|
|
275
|
+
Java below 17 blocks both backend modes. Report the source and prerequisite upgrade;
|
|
276
|
+
do not substitute an older SDK or install only the browser half.
|
|
277
|
+
|
|
278
|
+
#### Spring Boot 3, and separately Spring MVC
|
|
279
|
+
|
|
280
|
+
Check Boot version in the parent POM, dependency BOM, or Gradle plugin, and separately
|
|
281
|
+
identify the stack serving the route:
|
|
282
|
+
|
|
283
|
+
- `spring-boot-starter-web` / Spring MVC on Boot 3 and Java 17+ supports the starter.
|
|
284
|
+
- WebFlux without MVC does not support the annotation path; use backend Manual.
|
|
285
|
+
- If both stacks are present, determine which owns the route; ask if unclear.
|
|
286
|
+
- Boot 2.x and other Java frameworks use backend Manual when Java 17+ is established.
|
|
287
|
+
|
|
288
|
+
Report Java target, backend stack, available modes per layer, existing modes, and
|
|
289
|
+
blockers with source evidence before proceeding.
|
|
290
|
+
|
|
291
|
+
## Then act on what you found
|
|
292
|
+
|
|
293
|
+
Use this evidence to establish backend capabilities; do not select or migrate a mode
|
|
294
|
+
merely because the other option is available.
|
|
295
|
+
|
|
296
|
+
| Detected | Do this |
|
|
297
|
+
| --- | --- |
|
|
298
|
+
| Java < 17, or no Java backend | Stop before editing. Report the finding and its source; neither backend mode is supported. Name a supported Java backend as the prerequisite. |
|
|
299
|
+
| Java 17+, no Spring Boot 3 MVC | Backend Manual is the only option. State the capability limit; do not present backend Seamless as a choice. |
|
|
300
|
+
| Java 17+ and Spring Boot 3 MVC | Both backend modes are viable when their artifacts are released. Apply the selection rules below. |
|
|
301
|
+
| Ambiguous module, missing build file, version only in environment hints, or unclear MVC/WebFlux ownership | Ask, showing what you found. |
|
|
302
|
+
|
|
303
|
+
Report file/line evidence for the owning module, Java target, framework, and available
|
|
304
|
+
modes. Treat unknown values as clarification needs, not inferred compatibility.
|
|
305
|
+
|
|
306
|
+
## Choosing the modes
|
|
307
|
+
|
|
308
|
+
Choose one supported mode per layer using the capabilities above and the selected
|
|
309
|
+
browser reference's transport/carrier limits. Apply these priorities in order:
|
|
310
|
+
|
|
311
|
+
1. **Explicit preferences:** honor supported choices for each named layer. Explain
|
|
312
|
+
blockers and alternatives for unsupported choices; do not silently substitute.
|
|
313
|
+
2. **Existing integration:** preserve supported modes, including mixed pairs, unless
|
|
314
|
+
the user requests migration or evidence requires correction. Verify/docs tasks
|
|
315
|
+
observe modes rather than reopen selection. During migration, replace the old path
|
|
316
|
+
with the new one in the same change and release; preserve the other layer.
|
|
317
|
+
3. **One layer unselected:** recommend the matching mode if supported; otherwise a
|
|
318
|
+
compatible mixed pair. Do not change the selected layer just to match names.
|
|
319
|
+
4. **Both layers new:** recommend Seamless/Seamless when all release, stack, transport,
|
|
320
|
+
and carrier requirements hold; otherwise Manual/Manual when supported. If neither
|
|
321
|
+
pair works, explain the supported mixed pair or blocker.
|
|
322
|
+
|
|
323
|
+
Recommendations require the selection step below before implementation.
|
|
324
|
+
|
|
325
|
+
### Ask and wait before integration edits
|
|
326
|
+
|
|
327
|
+
For Install, ask about unselected layers using
|
|
328
|
+
[Interactive questions](../SKILL.md#interactive-questions). Present supported modes,
|
|
329
|
+
their differences, and the recommendation with its reason; even a single supported
|
|
330
|
+
option needs confirmation. Wait before integration edits, dependencies, or runtime
|
|
331
|
+
configuration changes; independent read-only discovery may continue.
|
|
332
|
+
|
|
333
|
+
An explicit supported preference already selects that layer. Preserve existing
|
|
334
|
+
supported modes. A general request to protect an endpoint, a recommendation, or silence
|
|
335
|
+
is not a choice. Do not repeat questions already answered.
|
|
336
|
+
|
|
337
|
+
The mode and script-URL questions may be combined, but each choice needs an answer;
|
|
338
|
+
choosing one does not choose the other.
|
|
339
|
+
|
|
340
|
+
Examples (frontend / backend):
|
|
341
|
+
|
|
342
|
+
| Situation | Recommendation |
|
|
343
|
+
| --- | --- |
|
|
344
|
+
| New Spring Boot 3 MVC + Java 17+, released Seamless support, page-scope `fetch` | Seamless / Seamless |
|
|
345
|
+
| New Java 17+ non-Boot or WebFlux backend; both layers otherwise unselected | Manual / Manual |
|
|
346
|
+
| User requests frontend Manual on Boot 3 MVC; backend not integrated | Manual / Manual |
|
|
347
|
+
| User requests frontend Seamless on a supported browser transport; backend is non-Boot Java 17+ | Seamless / Manual |
|
|
348
|
+
| Frontend Manual already paired with backend Seamless | Preserve Manual / Seamless |
|
|
349
|
+
| Frontend Seamless already paired with backend Manual | Preserve Seamless / Manual |
|
|
350
|
+
|
|
351
|
+
Different endpoints may use different pairs. A protected operation uses exactly one
|
|
352
|
+
frontend mode and one backend mode. Never combine `@RequestShieldProtected` and a
|
|
353
|
+
direct `RequestShieldClient.verify()` on one request: both consume the token, so the
|
|
354
|
+
second returns `token_replayed`. For the starter, state `BLOCK` or `MONITOR` separately
|
|
355
|
+
as the enforcement mode; integration-mode names are not values for that setting. For
|
|
356
|
+
direct core integration, describe the application's observed handling of `isAllowed()`
|
|
357
|
+
without inventing a starter-style configuration property.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Work outward from the request, not from the code. Most reports of "RequestShield is
|
|
4
|
+
broken" are one of four things: the browser never sent a token, the configured carrier
|
|
5
|
+
never reached verification, the backend never verified it, or one token was verified twice.
|
|
6
|
+
|
|
7
|
+
Name the observed frontend and backend integration modes separately: each can be
|
|
8
|
+
Seamless or Manual where supported. Backend Seamless uses the Spring Boot 3 MVC starter;
|
|
9
|
+
backend Manual uses explicit core SDK verification. A mixed pair alone is not a fault
|
|
10
|
+
or a reason to migrate. Keep integration modes distinct from `BLOCK`/`MONITOR`
|
|
11
|
+
enforcement behavior.
|
|
12
|
+
|
|
13
|
+
## First checks
|
|
14
|
+
|
|
15
|
+
Start with source inspection and runtime evidence already supplied by the user.
|
|
16
|
+
Browser requests and safe backend decision metrics provide evidence about runtime behavior;
|
|
17
|
+
collect new endpoint traffic only through the explicit Test flow.
|
|
18
|
+
|
|
19
|
+
For HTTP liveness, run `requestshield service status --json` without login or an
|
|
20
|
+
App Key. It checks Management API and Challenge Service at the caller's location
|
|
21
|
+
and time; it does not verify application protection or application integration.
|
|
22
|
+
Credential-status metadata remains unavailable; do not reveal a secret to check it.
|
|
23
|
+
|
|
24
|
+
If supplied evidence points to rejected backend credentials, explain the likely
|
|
25
|
+
configuration issue without reading secret values.
|
|
26
|
+
Credential management is a separate request.
|
|
27
|
+
|
|
28
|
+
## Reason codes
|
|
29
|
+
|
|
30
|
+
`result.getReason().getCode()` returns a stable code, safe to log. Use codes to explain
|
|
31
|
+
a decision, never to amend one.
|
|
32
|
+
|
|
33
|
+
The table below is a working list, not the authoritative one — the customer
|
|
34
|
+
documentation owns that. Check a code against it before quoting a meaning to the user,
|
|
35
|
+
and treat a code that is not listed here as unrecognised rather than guessing from its
|
|
36
|
+
name.
|
|
37
|
+
|
|
38
|
+
| Code | Means | Usual cause |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `ok` | Verified and consumed | — |
|
|
41
|
+
| `missing_token` | No token reached backend verification | Script tag absent or loaded after the request; frontend Seamless path mismatch (case, trailing slash, wrong origin); an uncovered transport (form POST, sendBeacon, sync XHR, `no-cors`); a frontend Manual call site that never populates the configured carrier; backend extraction reading a different carrier; or CSP missing a `cspAdditions` entry, such as `workerSrc` or `'wasm-unsafe-eval'`, so `getToken()` returns empty. |
|
|
42
|
+
| `unknown_customer` | App Key not recognised | Typo, deactivated key, or browser and backend configured with different App Keys. |
|
|
43
|
+
| `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. |
|
|
44
|
+
| `token_expired` | Token too old | The page held a token instead of obtaining a fresh one per request, or a very slow round trip. |
|
|
45
|
+
| `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 direct `verify()`, or a filter plus a controller). |
|
|
46
|
+
| `consume_unauthorized` | Backend credentials rejected | API Secret wrong, rotated, or not injected — explain the likely configuration issue from supplied evidence without reading the value. |
|
|
47
|
+
| `invalid_request` | Malformed verification request | Usually a mis-set `challenge-server-url`. |
|
|
48
|
+
| `not_found` | Token unknown to the platform | Cross-environment mismatch — a staging page's token verified against production, or the reverse. |
|
|
49
|
+
| `service_unavailable` | Platform unreachable | Check backend connectivity and safe health metrics. See degraded behaviour below. |
|
|
50
|
+
|
|
51
|
+
## "It blocks everything"
|
|
52
|
+
|
|
53
|
+
Almost always `missing_token` or `unknown_customer`. Confirm in this order — each step is
|
|
54
|
+
cheap and rules out a whole class:
|
|
55
|
+
|
|
56
|
+
1. Identify the carrier the backend actually reads: `X-IntelliFend-Token`, or a
|
|
57
|
+
documented dedicated body field for frontend Manual with backend Manual. Check
|
|
58
|
+
that carrier's presence and whether it is non-empty in the protected request;
|
|
59
|
+
do not record the token value. An absent header is expected for a body carrier.
|
|
60
|
+
2. **Token absent from the configured carrier** → frontend. Seamless: compare the requested URL against
|
|
61
|
+
the exact origin and `data-protect` path segments; each `:name` must match one non-empty
|
|
62
|
+
segment, and literal case and trailing slash are significant. Also
|
|
63
|
+
check the transport is `fetch` or async XHR from page scope. Manual: find the call
|
|
64
|
+
site, and every retry path.
|
|
65
|
+
3. **Header transport fails only across origins** → check CORS and preflight. The API's
|
|
66
|
+
`Access-Control-Allow-Headers` must include `X-IntelliFend-Token` when that header
|
|
67
|
+
is used, or the browser can block the request. This token-header requirement does
|
|
68
|
+
not apply to a body carrier; check CORS against that request's actual headers.
|
|
69
|
+
4. **Configured carrier empty** → check token acquisition. Check the CSP
|
|
70
|
+
includes every `cspAdditions` entry from `requestshield contract --json`,
|
|
71
|
+
then check connectivity and safe backend health observations. For frontend Manual
|
|
72
|
+
using the header, an empty token means the header should be omitted, not sent empty
|
|
73
|
+
— see `browser-manual.md`.
|
|
74
|
+
5. **Configured carrier populated** → backend half. Confirm extraction reads that
|
|
75
|
+
carrier unchanged, compare the App Key on both sides, then confirm runtime secret
|
|
76
|
+
injection by presence only.
|
|
77
|
+
|
|
78
|
+
## "It blocks nothing"
|
|
79
|
+
|
|
80
|
+
Enumerate rather than assuming the browser is at fault:
|
|
81
|
+
|
|
82
|
+
- The endpoint uses `MONITOR` enforcement — evaluating and always continuing. Protection-shaped,
|
|
83
|
+
not protection.
|
|
84
|
+
- The decision is computed but only logged, never enforced.
|
|
85
|
+
- Verification happens after the mutation has already been performed.
|
|
86
|
+
- Application code overrides `isAllowed()` from a reason code — a separate decision table
|
|
87
|
+
in application code removes the protection.
|
|
88
|
+
- The backend never verifies at all: a browser-only install. Grep for the client or the
|
|
89
|
+
annotation before trusting a claim that the backend is wired up.
|
|
90
|
+
- Results are `isDegraded()` — the platform was unreachable and requests were allowed by
|
|
91
|
+
the availability policy.
|
|
92
|
+
|
|
93
|
+
## Degraded results are allowed by design
|
|
94
|
+
|
|
95
|
+
When the Challenge Server cannot be reached, `verify()` returns a result that is
|
|
96
|
+
**allowed** and **degraded**. Availability is deliberately chosen over enforcement so a
|
|
97
|
+
platform outage cannot take down a customer's checkout flow.
|
|
98
|
+
|
|
99
|
+
Communicate the consequence clearly: during a degraded window, traffic passes without
|
|
100
|
+
real verification. Log the degraded rate as its own metric so it is visible, and check
|
|
101
|
+
backend connectivity and service health through established monitoring when it rises. Never "fix" a degraded result by overriding
|
|
102
|
+
`isAllowed()` — that converts a platform incident into a customer-facing outage.
|
|
103
|
+
|
|
104
|
+
## Confirming traffic and enforcement
|
|
105
|
+
|
|
106
|
+
Troubleshooting reads evidence the user already has; exercising the endpoint belongs to
|
|
107
|
+
the explicit Test flow in `SKILL.md`. There, use browser network observations and
|
|
108
|
+
existing safe backend metrics in an authorized environment. Do not record raw tokens or secrets. `requestshield usage <app-key>`
|
|
109
|
+
provides approximate recent request totals, defaulting to 24 hours within seven-day
|
|
110
|
+
retention. Missing or delayed logs can hide traffic; a zero count does not prove
|
|
111
|
+
enforcement or lack of traffic. Application status is not a traffic measurement. Report static correctness,
|
|
112
|
+
observed requests and backend enforcement separately. Use the controlled negative
|
|
113
|
+
test in `SKILL.md` to demonstrate enforcement.
|
|
114
|
+
|
|
115
|
+
## Secret exposure
|
|
116
|
+
|
|
117
|
+
If the API Secret appears in a repo, a log, a build artifact, or a chat transcript,
|
|
118
|
+
rotate it — deleting the line does not un-expose it. Follow the private-terminal
|
|
119
|
+
credential workflow in `SKILL.md`: explain the impact, warn that the replacement API
|
|
120
|
+
Secret is displayed only once, and obtain confirmation under
|
|
121
|
+
[Interactive questions](../SKILL.md#interactive-questions) before running:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
requestshield secret rotate <app-key> --idempotency-key <agent-generated-uuid> --yes
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Run that command only in a user-visible terminal whose output is unavailable to the
|
|
128
|
+
agent. The user stores the new secret privately and confirms only whether it was saved.
|
|
129
|
+
The App Key is unchanged, so no browser edit is needed. Rotation replaces the previous
|
|
130
|
+
secret, but changes may take a moment. A lost response can be recovered with explicit
|
|
131
|
+
reveal; an exposed secret requires rotation.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { access } from "node:fs/promises";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Detect supported agents from their executable or local configuration.
|
|
10
|
+
*
|
|
11
|
+
* @param {{ env?: NodeJS.ProcessEnv, homeDir?: string }} [options]
|
|
12
|
+
* @returns {Promise<Array<"codex" | "claude">>}
|
|
13
|
+
*/
|
|
14
|
+
export async function detectAgents(options = {}) {
|
|
15
|
+
|
|
16
|
+
const env = options.env ??
|
|
17
|
+
process.env;
|
|
18
|
+
|
|
19
|
+
const homeDir = options.homeDir ??
|
|
20
|
+
os.homedir();
|
|
21
|
+
|
|
22
|
+
const codexHome = env.CODEX_HOME ??
|
|
23
|
+
path.join(homeDir, ".codex");
|
|
24
|
+
|
|
25
|
+
const codexConfigPath =
|
|
26
|
+
path.join(codexHome, "config.toml");
|
|
27
|
+
|
|
28
|
+
const claudeConfigPath =
|
|
29
|
+
path.join(homeDir, ".claude.json");
|
|
30
|
+
|
|
31
|
+
// Executables prove the CLI is on PATH. Configuration files cover desktop
|
|
32
|
+
// installs and agents that were previously configured but are not on PATH.
|
|
33
|
+
const [codexCommand, claudeCommand, codexConfig, claudeConfig, claudeState] =
|
|
34
|
+
await Promise.all([
|
|
35
|
+
commandExists("codex", env),
|
|
36
|
+
commandExists("claude", env),
|
|
37
|
+
pathExists(codexHome),
|
|
38
|
+
pathExists(path.join(homeDir, ".claude")),
|
|
39
|
+
pathExists(path.join(homeDir, ".claude.json")),
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
/** @type {Array<"codex" | "claude">} */
|
|
43
|
+
const detected = [];
|
|
44
|
+
|
|
45
|
+
if (codexCommand || codexConfig) {
|
|
46
|
+
detected.push("codex")
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
if (claudeCommand || claudeConfig || claudeState) {
|
|
50
|
+
detected.push("claude")
|
|
51
|
+
};
|
|
52
|
+
return detected;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Inspect PATH without starting the coding agent.
|
|
57
|
+
*
|
|
58
|
+
* @param {string} command
|
|
59
|
+
* @param {NodeJS.ProcessEnv} env
|
|
60
|
+
*/
|
|
61
|
+
async function commandExists(command, env) {
|
|
62
|
+
|
|
63
|
+
const searchPath = env.PATH ??
|
|
64
|
+
env.Path ?? "";
|
|
65
|
+
|
|
66
|
+
const extensions =
|
|
67
|
+
process.platform === "win32"
|
|
68
|
+
? (env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM")
|
|
69
|
+
.split(";")
|
|
70
|
+
.filter(Boolean)
|
|
71
|
+
: [""];
|
|
72
|
+
|
|
73
|
+
for (const directory of searchPath.split(path.delimiter)) {
|
|
74
|
+
if (!directory) {
|
|
75
|
+
continue
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
for (const extension of extensions) {
|
|
79
|
+
try {
|
|
80
|
+
await access(
|
|
81
|
+
path.join(directory, `${command}${extension}`),
|
|
82
|
+
process.platform === "win32" ? constants.F_OK : constants.X_OK,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return true;
|
|
86
|
+
} catch {
|
|
87
|
+
// Continue through the remaining executable candidates.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @param {string} target */
|
|
95
|
+
async function pathExists(target) {
|
|
96
|
+
try {
|
|
97
|
+
await access(target);
|
|
98
|
+
return true;
|
|
99
|
+
} catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|