requestshield 0.1.4 → 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.
- package/README.md +421 -85
- package/config/.env.prod +7 -0
- package/package.json +21 -12
- package/skills/requestshield/SKILL.md +299 -307
- package/skills/requestshield/assets/AGENTS.codex.md +62 -62
- package/skills/requestshield/references/backend-java-core.md +128 -128
- package/skills/requestshield/references/backend-spring-boot.md +145 -145
- package/skills/requestshield/references/browser-manual.md +210 -210
- package/skills/requestshield/references/browser-seamless.md +156 -164
- package/skills/requestshield/references/cli.md +107 -182
- package/skills/requestshield/references/integration-planning.md +362 -389
- package/skills/requestshield/references/troubleshooting.md +114 -118
- package/src/agent-detector.mjs +102 -74
- package/src/api-client.mjs +115 -79
- package/src/args.mjs +140 -80
- package/src/browser-opener.mjs +32 -0
- package/src/cli.mjs +277 -51
- package/src/commands/agent-setup.mjs +182 -185
- package/src/commands/application-mutations.mjs +33 -0
- package/src/commands/application-response.mjs +55 -0
- package/src/commands/apps-get.mjs +20 -0
- package/src/commands/apps-list.mjs +94 -0
- package/src/commands/auth-status.mjs +37 -0
- package/src/commands/keys-create.mjs +7 -38
- package/src/commands/mutation-support.mjs +110 -0
- package/src/commands/secret-commands.mjs +45 -0
- package/src/commands/signin.mjs +70 -57
- package/src/commands/signout.mjs +9 -0
- package/src/commands/update-check.mjs +12 -4
- package/src/config.mjs +150 -0
- package/src/entrypoint.mjs +24 -0
- package/src/errors.mjs +3 -1
- package/src/main.mjs +5 -24
- package/src/oauth-client.mjs +153 -0
- package/src/oauth-loopback.mjs +120 -0
- package/src/session-files.mjs +213 -0
- package/src/session-store.mjs +177 -64
|
@@ -1,389 +1,362 @@
|
|
|
1
|
-
# Integration planning
|
|
2
|
-
|
|
3
|
-
Use this reference before writing or removing RequestShield integration code. It owns the
|
|
4
|
-
planning steps that are too detailed for `SKILL.md`.
|
|
5
|
-
|
|
6
|
-
## Workflow by operation
|
|
7
|
-
|
|
8
|
-
- **Install** -> `integration-planning.md` full flow: **Credentials check** ->
|
|
9
|
-
**Detect existing integration** -> **Contract check** -> **Gate** -> **Then act on
|
|
10
|
-
what you found** -> **Choosing the mode** -> **Installing** -> **Verifying** ->
|
|
11
|
-
**Negative test**.
|
|
12
|
-
- **Verify / Troubleshoot** -> `integration-planning.md` (Detect existing integration
|
|
13
|
-
only) -> **Verifying**. If a reason code, degraded result, browser mode, backend path,
|
|
14
|
-
or unknown state is involved, read only the matching reference files.
|
|
15
|
-
- **Uninstall** -> `integration-planning.md` (Detect existing integration only) ->
|
|
16
|
-
**Uninstalling**.
|
|
17
|
-
|
|
18
|
-
Do not couple browser mode to backend path. They are independent axes:
|
|
19
|
-
|
|
20
|
-
- Browser mode: Seamless (`browser-seamless.md`) or Manual (`browser-manual.md`).
|
|
21
|
-
- Backend path: Spring Boot 3 starter (`backend-spring-boot.md`) or Java core SDK
|
|
22
|
-
(`backend-java-core.md`).
|
|
23
|
-
|
|
24
|
-
Either browser mode may pair with either supported backend path. The backend stack
|
|
25
|
-
selects the backend path. The way the browser issues the protected request selects the
|
|
26
|
-
browser mode.
|
|
27
|
-
|
|
28
|
-
## Credentials check
|
|
29
|
-
|
|
30
|
-
The **pre-edit** check: confirm a credential source exists before touching backend
|
|
31
|
-
integration code. This step belongs to the Install full flow.
|
|
32
|
-
|
|
33
|
-
- **Install** — always, before editing backend code.
|
|
34
|
-
- **Verify / Troubleshoot** — do not run this as part of the operation route. Start with
|
|
35
|
-
**Detect existing integration only**, then use `troubleshooting.md` if the evidence
|
|
36
|
-
points to a credential failure.
|
|
37
|
-
- **Uninstall** — do not run this step; detect the existing integration only.
|
|
38
|
-
|
|
39
|
-
Diagnosing a credential *failure* is a different question, and `troubleshooting.md`
|
|
40
|
-
owns it — go there for `consume_unauthorized`, `unknown_customer`, or a backend
|
|
41
|
-
rejecting every token, whether or not this check has already passed.
|
|
42
|
-
|
|
43
|
-
RequestShield requires:
|
|
44
|
-
|
|
45
|
-
- an App Key
|
|
46
|
-
- an API Secret
|
|
47
|
-
|
|
48
|
-
Check for credential sources without printing, reading, or echoing their values. Confirm
|
|
49
|
-
presence only; never print, cat, or echo either value:
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
# Presence check only. Never print secret values.
|
|
53
|
-
|
|
54
|
-
if env | grep -Eq '^(INTELLIFEND_)?REQUESTSHIELD_(APP_KEY|KEY)='; then
|
|
55
|
-
echo "RequestShield App Key: present"
|
|
56
|
-
else
|
|
57
|
-
echo "RequestShield App Key: not found in current environment"
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
if env | grep -Eq '^(INTELLIFEND_)?REQUESTSHIELD_(API_SECRET|SECRET)='; then
|
|
61
|
-
echo "RequestShield API Secret: present"
|
|
62
|
-
else
|
|
63
|
-
echo "RequestShield API Secret: not found in current environment"
|
|
64
|
-
fi
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Common variable names are `INTELLIFEND_REQUESTSHIELD_APP_KEY`,
|
|
68
|
-
`REQUESTSHIELD_APP_KEY`, `REQUESTSHIELD_KEY`,
|
|
69
|
-
`INTELLIFEND_REQUESTSHIELD_API_SECRET`, `REQUESTSHIELD_API_SECRET`, and
|
|
70
|
-
`REQUESTSHIELD_SECRET`. A matching non-canonical name is only a credential candidate.
|
|
71
|
-
Confirm that the backend actually reads or maps that variable before treating it as a
|
|
72
|
-
valid RequestShield credential.
|
|
73
|
-
|
|
74
|
-
If the App Key is known,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
-g "*.
|
|
111
|
-
-g "*.
|
|
112
|
-
-g "
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
-g "
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
- **
|
|
174
|
-
|
|
175
|
-
- **
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
|
215
|
-
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
|
220
|
-
|
|
|
221
|
-
| **
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
in
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
rg -n "
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
|
343
|
-
|
|
|
344
|
-
|
|
|
345
|
-
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
released, and this operation not already integrated. If it landed on any other row of
|
|
364
|
-
that table, the mode is already decided — do not re-open it here.
|
|
365
|
-
|
|
366
|
-
This is the browser half. Backend path does not constrain it. Both browser modes deliver
|
|
367
|
-
the token in `X-IntelliFend-Token`, which either backend path reads.
|
|
368
|
-
|
|
369
|
-
| | **Seamless** | **Manual** |
|
|
370
|
-
| --- | --- | --- |
|
|
371
|
-
| Browser | `data-protect` lists exact endpoints; the SDK attaches tokens to matching `fetch` and async XHR requests. | `await IntelliFend.getToken()` at each protected call site, attached in application code. |
|
|
372
|
-
| Requires | The request travels by `fetch` or async XHR from page scope. | Nothing beyond the SDK and a supported carrier. |
|
|
373
|
-
| Code touched | One line of HTML. | Every protected call site, plus every retry path. |
|
|
374
|
-
| Backend work | Identical either way: whichever backend path the Gate selected. | Identical either way: whichever backend path the Gate selected. |
|
|
375
|
-
|
|
376
|
-
Released-mode availability was already settled at **Contract check**. One question is
|
|
377
|
-
left: does the protected request travel by `fetch` or asynchronous `XMLHttpRequest` from
|
|
378
|
-
page scope? Native form POST, `sendBeacon`, WebSocket/EventSource, synchronous XHR,
|
|
379
|
-
`no-cors`, and service-worker-owned requests are not intercepted — read
|
|
380
|
-
`browser-seamless.md` for the full coverage list.
|
|
381
|
-
|
|
382
|
-
Recommend Seamless when that check passes. It touches one line instead of every call
|
|
383
|
-
site, so there is no missed call site or retry path. If it fails, use Manual and give
|
|
384
|
-
the reason; that is a finding, not a preference.
|
|
385
|
-
|
|
386
|
-
A given protected operation uses one mode, not both. Different endpoints on the same
|
|
387
|
-
page may use different modes when necessary. Never use two backend verification paths on
|
|
388
|
-
one request; `@RequestShieldProtected` and manual `RequestShieldClient.verify()` both
|
|
389
|
-
consume the token, so the second returns `token_replayed`.
|
|
1
|
+
# Integration planning
|
|
2
|
+
|
|
3
|
+
Use this reference before writing or removing RequestShield integration code. It owns the
|
|
4
|
+
planning steps that are too detailed for `SKILL.md`.
|
|
5
|
+
|
|
6
|
+
## Workflow by operation
|
|
7
|
+
|
|
8
|
+
- **Install** -> `integration-planning.md` full flow: **Credentials check** ->
|
|
9
|
+
**Detect existing integration** -> **Contract check** -> **Gate** -> **Then act on
|
|
10
|
+
what you found** -> **Choosing the mode** -> **Installing** -> **Verifying** ->
|
|
11
|
+
**Negative test**.
|
|
12
|
+
- **Verify / Troubleshoot** -> `integration-planning.md` (Detect existing integration
|
|
13
|
+
only) -> **Verifying**. If a reason code, degraded result, browser mode, backend path,
|
|
14
|
+
or unknown state is involved, read only the matching reference files.
|
|
15
|
+
- **Uninstall** -> `integration-planning.md` (Detect existing integration only) ->
|
|
16
|
+
**Uninstalling**.
|
|
17
|
+
|
|
18
|
+
Do not couple browser mode to backend path. They are independent axes:
|
|
19
|
+
|
|
20
|
+
- Browser mode: Seamless (`browser-seamless.md`) or Manual (`browser-manual.md`).
|
|
21
|
+
- Backend path: Spring Boot 3 starter (`backend-spring-boot.md`) or Java core SDK
|
|
22
|
+
(`backend-java-core.md`).
|
|
23
|
+
|
|
24
|
+
Either browser mode may pair with either supported backend path. The backend stack
|
|
25
|
+
selects the backend path. The way the browser issues the protected request selects the
|
|
26
|
+
browser mode.
|
|
27
|
+
|
|
28
|
+
## Credentials check
|
|
29
|
+
|
|
30
|
+
The **pre-edit** check: confirm a credential source exists before touching backend
|
|
31
|
+
integration code. This step belongs to the Install full flow.
|
|
32
|
+
|
|
33
|
+
- **Install** — always, before editing backend code.
|
|
34
|
+
- **Verify / Troubleshoot** — do not run this as part of the operation route. Start with
|
|
35
|
+
**Detect existing integration only**, then use `troubleshooting.md` if the evidence
|
|
36
|
+
points to a credential failure.
|
|
37
|
+
- **Uninstall** — do not run this step; detect the existing integration only.
|
|
38
|
+
|
|
39
|
+
Diagnosing a credential *failure* is a different question, and `troubleshooting.md`
|
|
40
|
+
owns it — go there for `consume_unauthorized`, `unknown_customer`, or a backend
|
|
41
|
+
rejecting every token, whether or not this check has already passed.
|
|
42
|
+
|
|
43
|
+
RequestShield requires:
|
|
44
|
+
|
|
45
|
+
- an App Key
|
|
46
|
+
- an API Secret
|
|
47
|
+
|
|
48
|
+
Check for credential sources without printing, reading, or echoing their values. Confirm
|
|
49
|
+
presence only; never print, cat, or echo either value:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Presence check only. Never print secret values.
|
|
53
|
+
|
|
54
|
+
if env | grep -Eq '^(INTELLIFEND_)?REQUESTSHIELD_(APP_KEY|KEY)='; then
|
|
55
|
+
echo "RequestShield App Key: present"
|
|
56
|
+
else
|
|
57
|
+
echo "RequestShield App Key: not found in current environment"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if env | grep -Eq '^(INTELLIFEND_)?REQUESTSHIELD_(API_SECRET|SECRET)='; then
|
|
61
|
+
echo "RequestShield API Secret: present"
|
|
62
|
+
else
|
|
63
|
+
echo "RequestShield API Secret: not found in current environment"
|
|
64
|
+
fi
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Common variable names are `INTELLIFEND_REQUESTSHIELD_APP_KEY`,
|
|
68
|
+
`REQUESTSHIELD_APP_KEY`, `REQUESTSHIELD_KEY`,
|
|
69
|
+
`INTELLIFEND_REQUESTSHIELD_API_SECRET`, `REQUESTSHIELD_API_SECRET`, and
|
|
70
|
+
`REQUESTSHIELD_SECRET`. A matching non-canonical name is only a credential candidate.
|
|
71
|
+
Confirm that the backend actually reads or maps that variable before treating it as a
|
|
72
|
+
valid RequestShield credential.
|
|
73
|
+
|
|
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.
|
|
78
|
+
|
|
79
|
+
A credential that is not present in the current shell is not necessarily missing from
|
|
80
|
+
the deployed backend. It may be injected at runtime by a secret manager, CI/CD system,
|
|
81
|
+
container runtime, Kubernetes Secret, or deployment environment.
|
|
82
|
+
|
|
83
|
+
Report only what was confirmed:
|
|
84
|
+
|
|
85
|
+
| Finding | Action |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| Both credential sources are confirmed | Continue. Never read their values. |
|
|
88
|
+
| A non-canonical variable is found and its backend mapping is confirmed | Report the mapping and continue. |
|
|
89
|
+
| Credentials are provisioned, but the runtime source is unknown | Ask how the deployed backend receives them before editing backend integration code. |
|
|
90
|
+
| No credential source can be confirmed | Report the uncertainty and ask before proceeding. |
|
|
91
|
+
| No credential pair has been provisioned | Ask the user to provision credentials before continuing with backend setup. |
|
|
92
|
+
|
|
93
|
+
If no pair has been provisioned yet, the user creates it. You may run the read-only
|
|
94
|
+
`requestshield apps list` to see whether an application already exists. Everything that
|
|
95
|
+
mints or changes a secret stays with the user; see **Key and secret management** in
|
|
96
|
+
`SKILL.md`.
|
|
97
|
+
|
|
98
|
+
## Detect existing integration
|
|
99
|
+
|
|
100
|
+
Search for existing RequestShield code before install, verify/troubleshoot, or uninstall.
|
|
101
|
+
Use `rg` when available. Use `rg -l` for filename-only discovery.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
Browser markers:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
rg -l "data-app-key|data-protect|IntelliFend|X-IntelliFend-Token" \
|
|
108
|
+
-g "*.html" -g "*.htm" -g "*.js" -g "*.jsx" -g "*.ts" -g "*.tsx" \
|
|
109
|
+
-g "*.vue" -g "*.svelte" -g "*.astro" \
|
|
110
|
+
-g "*.erb" -g "*.haml" -g "*.php" -g "*.jinja*" -g "*.j2" -g "*.twig" \
|
|
111
|
+
-g "*.hbs" -g "*.ejs" -g "*.pug" -g "*.blade.php" \
|
|
112
|
+
-g "!node_modules/**" -g "!**/skills/**" -g "!**/.requestshield/**" .
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The tag often lives in a server-rendered layout rather than a static `.html` — a Django,
|
|
116
|
+
Rails, Laravel, or Thymeleaf base template — so a scan limited to `.html`/`.js` reports
|
|
117
|
+
"not integrated" on a codebase that already has one, and the install then adds a second
|
|
118
|
+
tag. If the app's templates use an extension not listed above, add it before concluding.
|
|
119
|
+
|
|
120
|
+
Backend markers:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
rg -l "RequestShieldClient|RequestShieldProtected|intellifend|requestshield" \
|
|
124
|
+
-g "*.java" -g "*.kt" -g "*.xml" -g "*.yml" -g "*.yaml" \
|
|
125
|
+
-g "*.gradle" -g "*.gradle.kts" \
|
|
126
|
+
-g "!**/skills/**" -g "!**/.requestshield/**" .
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`rg -l` returns candidate filenames only. Do not follow it with `cat`, an unrestricted
|
|
130
|
+
`sed`, plain `rg -n` without `-o`, or another command that exposes complete matching
|
|
131
|
+
lines or the entire file.
|
|
132
|
+
|
|
133
|
+
Locate known markers without returning the rest of their lines:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
rg -n -o \
|
|
137
|
+
"data-app-key|data-protect|IntelliFend|getToken|X-IntelliFend-Token" \
|
|
138
|
+
<browser-candidate-file>
|
|
139
|
+
|
|
140
|
+
rg -n -o \
|
|
141
|
+
"RequestShieldClient|RequestShieldProtected|verify|isAllowed|intellifend|requestshield" \
|
|
142
|
+
<backend-candidate-file>
|
|
143
|
+
|
|
144
|
+
rg -n -o \
|
|
145
|
+
"(INTELLIFEND_)?REQUESTSHIELD_(APP_KEY|KEY|API_SECRET|SECRET)" \
|
|
146
|
+
<candidate-configuration-file>
|
|
147
|
+
```
|
|
148
|
+
-o prints only the matched marker or environment-variable name, not the surrounding
|
|
149
|
+
value. Environment-variable names are safe to report; their values are not.
|
|
150
|
+
|
|
151
|
+
When configuration context is required, inspect it only through a secret-aware parser
|
|
152
|
+
or redacted view that masks sensitive values before stdout reaches the agent. Its output
|
|
153
|
+
may contain the filename, line number, configuration key, environment-variable name,
|
|
154
|
+
App Key when needed to identify the integration, and whether the source is an
|
|
155
|
+
environment reference, secret-manager reference, or literal.
|
|
156
|
+
|
|
157
|
+
Replace every API Secret, RequestShield token, session value, CSRF value,
|
|
158
|
+
authorization credential, and other credential literal with <redacted>.
|
|
159
|
+
|
|
160
|
+
If no secret-aware parser or redacted view is available, do not read the candidate
|
|
161
|
+
configuration file verbatim. Ask the user for a sanitized excerpt instead. Switching
|
|
162
|
+
to rg -l and then reading the entire candidate file is not safe.
|
|
163
|
+
|
|
164
|
+
The exclusions matter when this skill is installed inside the repo being scanned —
|
|
165
|
+
browser and backend reference files contain marker strings and would otherwise read as
|
|
166
|
+
an existing integration.
|
|
167
|
+
|
|
168
|
+
Report one of:
|
|
169
|
+
|
|
170
|
+
- **Not integrated**: no browser or backend markers.
|
|
171
|
+
- **Browser only**: tokens may be obtained or attached, but no backend enforcement was
|
|
172
|
+
found. This looks protected and is not.
|
|
173
|
+
- **Backend only**: enforcement exists, but no page sends a token. In BLOCK mode this can
|
|
174
|
+
reject legitimate users.
|
|
175
|
+
- **Fully integrated**: browser mode and backend path are both present. Name both.
|
|
176
|
+
|
|
177
|
+
If a script tag already exists, update it instead of adding a second one. The SDK
|
|
178
|
+
initializes from `document.currentScript`; two tags mean two configurations, and the
|
|
179
|
+
last one to run wins rather than the two merging.
|
|
180
|
+
|
|
181
|
+
## Contract check
|
|
182
|
+
|
|
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.
|
|
199
|
+
|
|
200
|
+
## Gate
|
|
201
|
+
|
|
202
|
+
The backend path is decided by the backend stack, not by browser preference. Establish
|
|
203
|
+
this before proposing edits. Discovering a backend blocker after the browser half is
|
|
204
|
+
written leaves tokens flowing with nothing enforcing them.
|
|
205
|
+
|
|
206
|
+
An integration is one backend path plus one browser mode, and they are independent
|
|
207
|
+
choices. A non-Spring-MVC backend does not rule out Seamless mode; it only rules out the
|
|
208
|
+
Spring Boot 3 starter backend path.
|
|
209
|
+
|
|
210
|
+
Backend path:
|
|
211
|
+
|
|
212
|
+
| Backend path | Requirement | Reference |
|
|
213
|
+
| --- | --- | --- |
|
|
214
|
+
| **Spring Boot 3 starter** | Spring Boot 3 with Spring MVC, and Java 17+ | `backend-spring-boot.md` |
|
|
215
|
+
| **Java core SDK** | Java 17+ | `backend-java-core.md` |
|
|
216
|
+
|
|
217
|
+
Browser mode:
|
|
218
|
+
|
|
219
|
+
| Browser mode | Use when | Reference |
|
|
220
|
+
| --- | --- | --- |
|
|
221
|
+
| **Seamless** | The page reaches the endpoint with `fetch` or async `XMLHttpRequest` | `browser-seamless.md` |
|
|
222
|
+
| **Manual** | The call needs explicit token timing, or a non-header carrier | `browser-manual.md` |
|
|
223
|
+
|
|
224
|
+
Either browser mode pairs with either backend path. The token travels in
|
|
225
|
+
`X-IntelliFend-Token` regardless. Java below 17 blocks both backend paths, and no amount
|
|
226
|
+
of browser-side work substitutes for backend enforcement.
|
|
227
|
+
|
|
228
|
+
### Run the check
|
|
229
|
+
|
|
230
|
+
Find the build file for the module that serves the protected endpoint, not the first one
|
|
231
|
+
in the tree. In a monorepo, locate the route first:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
find . -maxdepth 4 \( -name pom.xml -o -name "build.gradle*" \) \
|
|
235
|
+
-not -path "*/node_modules/*" -not -path "*/build/*" -not -path "*/target/*"
|
|
236
|
+
rg -n "/api/register" -g "*.java" -g "*.kt" .
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
One build file, inspect it. Several, and the route cannot be tied to one of them — or
|
|
240
|
+
several backends could plausibly serve it — **stop and ask which service owns the
|
|
241
|
+
endpoint.** Two backends in a monorepo can differ in both Java version and framework, so
|
|
242
|
+
a guess here invalidates the whole integration rather than needing a tweak.
|
|
243
|
+
|
|
244
|
+
Use repo-wide build-file scans only for discovery. Do not combine a route found in one
|
|
245
|
+
module with Java or Spring evidence from another module.
|
|
246
|
+
|
|
247
|
+
#### Java target version
|
|
248
|
+
|
|
249
|
+
Read the *project's target*, never the machine's JDK.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
rg -n "maven\.compiler\.(release|source|target)|<release>|<java\.version>" <owning-pom.xml>
|
|
253
|
+
rg -n "languageVersion|sourceCompatibility|jvmToolchain|JavaVersion" <owning-build.gradle*>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
- **Maven** — `maven.compiler.release`, or the compiler plugin's `<release>`, is
|
|
257
|
+
authoritative. Spring Boot's parent POM exposes `<java.version>`, which is the
|
|
258
|
+
idiomatic place in a Boot app. **Check the parent POM too** when the module inherits;
|
|
259
|
+
the value is often not in the module's own file.
|
|
260
|
+
- **Gradle** — `java.toolchain.languageVersion = JavaLanguageVersion.of(21)` and
|
|
261
|
+
`kotlin { jvmToolchain(21) }` are both authoritative, and both easy to miss because
|
|
262
|
+
they sit inside a block rather than on a property line.
|
|
263
|
+
- **When the build file says nothing** — `.java-version`, `.sdkmanrc`, `.tool-versions`,
|
|
264
|
+
a `setup-java` step's `java-version` in `.github/workflows/`, or a JDK base image in a
|
|
265
|
+
`Dockerfile`. These are **hints, not answers**: they describe an environment, which can
|
|
266
|
+
differ from what the build compiles against. A build file that yields only hints is the
|
|
267
|
+
ambiguous row below — ask.
|
|
268
|
+
- `java -version` reports the **local** JDK. A repo targeting 11 builds fine on a machine
|
|
269
|
+
with 21 installed, so it is a last-resort hint and never evidence.
|
|
270
|
+
|
|
271
|
+
Java below 17 blocks **both** backend paths. Report the version and its source and name
|
|
272
|
+
the upgrade as the prerequisite; do not fall back to an older SDK version or write a
|
|
273
|
+
partial browser-only integration.
|
|
274
|
+
|
|
275
|
+
#### Spring Boot 3, and separately Spring MVC
|
|
276
|
+
|
|
277
|
+
Two conditions. Both must hold for the Spring Boot starter.
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
rg -n "spring-boot-starter-parent|spring-boot-dependencies|org\.springframework\.boot" \
|
|
281
|
+
<owning-pom.xml-or-build.gradle*> | rg "3\.[0-9]+"
|
|
282
|
+
rg -n "spring-boot-starter-web[\"' :<]|spring-boot-starter-webflux|spring-webmvc" \
|
|
283
|
+
<owning-pom.xml-or-build.gradle*>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Read the parent version, the `spring-boot-dependencies` BOM version, or the Gradle plugin
|
|
287
|
+
version. **Spring Boot 2.x does not qualify** — the starter is a Boot 3 artifact, so a
|
|
288
|
+
2.x app needs the core SDK path even though it is Spring.
|
|
289
|
+
|
|
290
|
+
Then MVC versus WebFlux — the trap worth checking every time:
|
|
291
|
+
|
|
292
|
+
- `spring-boot-starter-web` → Spring MVC. The starter is available when the app is also
|
|
293
|
+
Spring Boot 3 on Java 17+.
|
|
294
|
+
- `spring-boot-starter-webflux` with no `-web` → **not** Spring MVC. The starter protects
|
|
295
|
+
Spring MVC handler methods, so `@RequestShieldProtected` does not apply. Such an app is
|
|
296
|
+
Spring Boot 3 on Java 17+ and still needs the Java core SDK — say so explicitly,
|
|
297
|
+
because "Spring Boot 3, Java 21" reads like a starter green light and quietly is not.
|
|
298
|
+
Browser mode is unaffected; Seamless remains available when the request transport
|
|
299
|
+
matches.
|
|
300
|
+
- **Both present** → determine which stack serves the protected route. A
|
|
301
|
+
`@RestController` returning `Mono`/`Flux`, or a `RouterFunction`, indicates the
|
|
302
|
+
reactive path. Ask if it stays unclear.
|
|
303
|
+
|
|
304
|
+
Also not Spring MVC, and therefore the Java core SDK backend path: **Quarkus, Micronaut,
|
|
305
|
+
Dropwizard, Helidon, Ktor, Vert.x, Jakarta EE / JAX-RS on its own, and a plain servlet
|
|
306
|
+
application.**
|
|
307
|
+
|
|
308
|
+
## Then act on what you found
|
|
309
|
+
|
|
310
|
+
This decision chooses the backend path only. Pick the browser mode separately from how
|
|
311
|
+
the page issues the protected request.
|
|
312
|
+
|
|
313
|
+
| Detected | Do this |
|
|
314
|
+
| --- | --- |
|
|
315
|
+
| Java < 17, or no Java backend | Stop before editing. Report the finding and its source; no backend path is available, so nothing can enforce. Name the upgrade as the prerequisite. |
|
|
316
|
+
| Java 17+, no Spring Boot 3 MVC | Use Java core SDK. It is the only backend option; state it rather than asking a fake choice. |
|
|
317
|
+
| Java 17+ and Spring Boot 3 MVC | Both backend paths are viable. Recommend the starter and confirm once. |
|
|
318
|
+
| Ambiguous module, missing build file, version only in environment hints, or unclear MVC/WebFlux ownership | Ask, showing what you found. |
|
|
319
|
+
|
|
320
|
+
Always report the evidence with file and line references:
|
|
321
|
+
|
|
322
|
+
```text
|
|
323
|
+
Backend: theair-customer-backend/build.gradle.kts
|
|
324
|
+
Java 21 - java.toolchain.languageVersion (line 14)
|
|
325
|
+
Spring Boot 3.2.1 - org.springframework.boot plugin (line 3)
|
|
326
|
+
Spring MVC - spring-boot-starter-web (line 20)
|
|
327
|
+
Backend path: Spring Boot 3 starter. Browser mode still depends on released modes and request transport.
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Detection is inference from build files. If any line would read "unknown", ask rather
|
|
331
|
+
than assume.
|
|
332
|
+
|
|
333
|
+
## Choosing the mode
|
|
334
|
+
|
|
335
|
+
Reach this section only when **Contract check** left a genuine choice: both modes
|
|
336
|
+
released, and this operation not already integrated. If it landed on any other row of
|
|
337
|
+
that table, the mode is already decided — do not re-open it here.
|
|
338
|
+
|
|
339
|
+
This is the browser half. Backend path does not constrain it. Both browser modes deliver
|
|
340
|
+
the token in `X-IntelliFend-Token`, which either backend path reads.
|
|
341
|
+
|
|
342
|
+
| | **Seamless** | **Manual** |
|
|
343
|
+
| --- | --- | --- |
|
|
344
|
+
| Browser | `data-protect` lists exact endpoints; the SDK attaches tokens to matching `fetch` and async XHR requests. | `await IntelliFend.getToken()` at each protected call site, attached in application code. |
|
|
345
|
+
| Requires | The request travels by `fetch` or async XHR from page scope. | Nothing beyond the SDK and a supported carrier. |
|
|
346
|
+
| Code touched | One line of HTML. | Every protected call site, plus every retry path. |
|
|
347
|
+
| Backend work | Identical either way: whichever backend path the Gate selected. | Identical either way: whichever backend path the Gate selected. |
|
|
348
|
+
|
|
349
|
+
Released-mode availability was already settled at **Contract check**. One question is
|
|
350
|
+
left: does the protected request travel by `fetch` or asynchronous `XMLHttpRequest` from
|
|
351
|
+
page scope? Native form POST, `sendBeacon`, WebSocket/EventSource, synchronous XHR,
|
|
352
|
+
`no-cors`, and service-worker-owned requests are not intercepted — read
|
|
353
|
+
`browser-seamless.md` for the full coverage list.
|
|
354
|
+
|
|
355
|
+
Recommend Seamless when that check passes. It touches one line instead of every call
|
|
356
|
+
site, so there is no missed call site or retry path. If it fails, use Manual and give
|
|
357
|
+
the reason; that is a finding, not a preference.
|
|
358
|
+
|
|
359
|
+
A given protected operation uses one mode, not both. Different endpoints on the same
|
|
360
|
+
page may use different modes when necessary. Never use two backend verification paths on
|
|
361
|
+
one request; `@RequestShieldProtected` and manual `RequestShieldClient.verify()` both
|
|
362
|
+
consume the token, so the second returns `token_replayed`.
|