requestshield 0.1.2 → 0.1.3
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 +75 -181
- package/package.json +13 -11
- package/skills/requestshield/SKILL.md +302 -39
- package/skills/requestshield/assets/AGENTS.codex.md +62 -0
- package/skills/requestshield/references/backend-java-core.md +128 -0
- package/skills/requestshield/references/backend-spring-boot.md +145 -0
- package/skills/requestshield/references/browser-manual.md +210 -0
- package/skills/requestshield/references/browser-seamless.md +164 -0
- package/skills/requestshield/references/cli.md +182 -0
- package/skills/requestshield/references/integration-planning.md +389 -0
- package/skills/requestshield/references/troubleshooting.md +118 -0
- package/src/agent-detector.mjs +74 -0
- package/src/args.mjs +23 -66
- package/src/cli.mjs +2 -13
- package/src/commands/agent-setup.mjs +109 -15
- package/src/main.mjs +24 -24
- package/src/commands/update-check.mjs +0 -139
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# `requestshield` CLI reference
|
|
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
|
|
40
|
+
```
|
|
41
|
+
|
|
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".
|
|
114
|
+
|
|
115
|
+
## Applications
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
requestshield apps list
|
|
119
|
+
requestshield apps get <app-key>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**auth.** `apps list` returns the applications the current user can access, each with
|
|
123
|
+
`app_key`, `name`, and `status`. Use it to resolve a human-supplied app name to a key
|
|
124
|
+
rather than asking the user to retype one.
|
|
125
|
+
|
|
126
|
+
`apps get <app-key>` returns `app_id`, `app_name`, and `status`. Status distinguishes a
|
|
127
|
+
key that has never seen traffic (`ready`) from one in normal service (`active`) — which
|
|
128
|
+
is exactly the difference between "the integration is not wired up yet" and "it is
|
|
129
|
+
working", so check it before spending time debugging code.
|
|
130
|
+
|
|
131
|
+
## Credentials
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
requestshield credentials status <app-key>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**auth.** Returns metadata only — `provisioned`, `active`, `shared` — and never the
|
|
138
|
+
secret value. Use it to answer "is the secret configured?" without anyone having to
|
|
139
|
+
paste a credential. A key that is `provisioned: false` explains backend failures far
|
|
140
|
+
faster than reading code.
|
|
141
|
+
|
|
142
|
+
## Service and monitoring
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
requestshield server
|
|
146
|
+
requestshield challenge volume <app-key> [--from <time>] [--to <time>] [--granularity <value>]
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**auth.** `server` reports `healthy` or `degraded`. Check it first when an integration
|
|
150
|
+
that was working starts behaving oddly — a degraded platform explains fail-open
|
|
151
|
+
behaviour on the backend without anything being wrong in the customer's code.
|
|
152
|
+
|
|
153
|
+
`challenge volume` is runtime evidence that the browser/platform half is active. It is
|
|
154
|
+
not proof that the protected backend enforces a blocking decision; the controlled
|
|
155
|
+
negative test in `SKILL.md` provides that evidence. Times are ISO-8601
|
|
156
|
+
(`2026-08-01T00:00:00Z`); `--granularity` takes values such as `hour` or `day`. A
|
|
157
|
+
`challenge_count` of zero after the user has exercised the endpoint means the browser
|
|
158
|
+
half is not firing — that is a browser-side bug, not a backend one, so start with the
|
|
159
|
+
mode's reference file.
|
|
160
|
+
|
|
161
|
+
## Billing
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
requestshield get billing
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**auth.** Current plan and usage for the application. Read-only; surface it when the
|
|
168
|
+
user asks about cost or limits.
|
|
169
|
+
|
|
170
|
+
## Agent integration
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
requestshield agent setup
|
|
174
|
+
requestshield agent setup --agent claude
|
|
175
|
+
requestshield agent setup --agent codex
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Local setup. Installs this skill for the named agent. With no `--agent`, the CLI detects
|
|
179
|
+
which agent is in use. Run it when the user wants the skill available in another repo or
|
|
180
|
+
for the other agent; it is the supported alternative to copying files by hand. It should
|
|
181
|
+
not require a RequestShield App Key or API Secret, and it must not create, rotate, or
|
|
182
|
+
deactivate customer credentials.
|
|
@@ -0,0 +1,389 @@
|
|
|
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, also confirm server-side credential state without exposing the
|
|
75
|
+
secret:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
requestshield credentials status <app-key>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
A credential that is not present in the current shell is not necessarily missing from
|
|
82
|
+
the deployed backend. It may be injected at runtime by a secret manager, CI/CD system,
|
|
83
|
+
container runtime, Kubernetes Secret, or deployment environment.
|
|
84
|
+
|
|
85
|
+
Report only what was confirmed:
|
|
86
|
+
|
|
87
|
+
| Finding | Action |
|
|
88
|
+
| --- | --- |
|
|
89
|
+
| Both credential sources are confirmed | Continue. Never read their values. |
|
|
90
|
+
| A non-canonical variable is found and its backend mapping is confirmed | Report the mapping and continue. |
|
|
91
|
+
| Credentials are provisioned, but the runtime source is unknown | Ask how the deployed backend receives them before editing backend integration code. |
|
|
92
|
+
| No credential source can be confirmed | Report the uncertainty and ask before proceeding. |
|
|
93
|
+
| No credential pair has been provisioned | Ask the user to provision credentials before continuing with backend setup. |
|
|
94
|
+
|
|
95
|
+
If no pair has been provisioned yet, the user creates it. You may run the read-only
|
|
96
|
+
`requestshield apps list` to see whether an application already exists. Everything that
|
|
97
|
+
mints or changes a secret stays with the user; see **Key and secret management** in
|
|
98
|
+
`SKILL.md`.
|
|
99
|
+
|
|
100
|
+
## Detect existing integration
|
|
101
|
+
|
|
102
|
+
Search for existing RequestShield code before install, verify/troubleshoot, or uninstall.
|
|
103
|
+
Use `rg` when available. Use `rg -l` for filename-only discovery.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
Browser markers:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
rg -l "data-app-key|data-protect|IntelliFend|X-IntelliFend-Token" \
|
|
110
|
+
-g "*.html" -g "*.htm" -g "*.js" -g "*.jsx" -g "*.ts" -g "*.tsx" \
|
|
111
|
+
-g "*.vue" -g "*.svelte" -g "*.astro" \
|
|
112
|
+
-g "*.erb" -g "*.haml" -g "*.php" -g "*.jinja*" -g "*.j2" -g "*.twig" \
|
|
113
|
+
-g "*.hbs" -g "*.ejs" -g "*.pug" -g "*.blade.php" \
|
|
114
|
+
-g "!node_modules/**" -g "!**/skills/**" -g "!**/.requestshield/**" .
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The tag often lives in a server-rendered layout rather than a static `.html` — a Django,
|
|
118
|
+
Rails, Laravel, or Thymeleaf base template — so a scan limited to `.html`/`.js` reports
|
|
119
|
+
"not integrated" on a codebase that already has one, and the install then adds a second
|
|
120
|
+
tag. If the app's templates use an extension not listed above, add it before concluding.
|
|
121
|
+
|
|
122
|
+
Backend markers:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
rg -l "RequestShieldClient|RequestShieldProtected|intellifend|requestshield" \
|
|
126
|
+
-g "*.java" -g "*.kt" -g "*.xml" -g "*.yml" -g "*.yaml" \
|
|
127
|
+
-g "*.gradle" -g "*.gradle.kts" \
|
|
128
|
+
-g "!**/skills/**" -g "!**/.requestshield/**" .
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`rg -l` returns candidate filenames only. Do not follow it with `cat`, an unrestricted
|
|
132
|
+
`sed`, plain `rg -n` without `-o`, or another command that exposes complete matching
|
|
133
|
+
lines or the entire file.
|
|
134
|
+
|
|
135
|
+
Locate known markers without returning the rest of their lines:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
rg -n -o \
|
|
139
|
+
"data-app-key|data-protect|IntelliFend|getToken|X-IntelliFend-Token" \
|
|
140
|
+
<browser-candidate-file>
|
|
141
|
+
|
|
142
|
+
rg -n -o \
|
|
143
|
+
"RequestShieldClient|RequestShieldProtected|verify|isAllowed|intellifend|requestshield" \
|
|
144
|
+
<backend-candidate-file>
|
|
145
|
+
|
|
146
|
+
rg -n -o \
|
|
147
|
+
"(INTELLIFEND_)?REQUESTSHIELD_(APP_KEY|KEY|API_SECRET|SECRET)" \
|
|
148
|
+
<candidate-configuration-file>
|
|
149
|
+
```
|
|
150
|
+
-o prints only the matched marker or environment-variable name, not the surrounding
|
|
151
|
+
value. Environment-variable names are safe to report; their values are not.
|
|
152
|
+
|
|
153
|
+
When configuration context is required, inspect it only through a secret-aware parser
|
|
154
|
+
or redacted view that masks sensitive values before stdout reaches the agent. Its output
|
|
155
|
+
may contain the filename, line number, configuration key, environment-variable name,
|
|
156
|
+
App Key when needed to identify the integration, and whether the source is an
|
|
157
|
+
environment reference, secret-manager reference, or literal.
|
|
158
|
+
|
|
159
|
+
Replace every API Secret, RequestShield token, session value, CSRF value,
|
|
160
|
+
authorization credential, and other credential literal with <redacted>.
|
|
161
|
+
|
|
162
|
+
If no secret-aware parser or redacted view is available, do not read the candidate
|
|
163
|
+
configuration file verbatim. Ask the user for a sanitized excerpt instead. Switching
|
|
164
|
+
to rg -l and then reading the entire candidate file is not safe.
|
|
165
|
+
|
|
166
|
+
The exclusions matter when this skill is installed inside the repo being scanned —
|
|
167
|
+
browser and backend reference files contain marker strings and would otherwise read as
|
|
168
|
+
an existing integration.
|
|
169
|
+
|
|
170
|
+
Report one of:
|
|
171
|
+
|
|
172
|
+
- **Not integrated**: no browser or backend markers.
|
|
173
|
+
- **Browser only**: tokens may be obtained or attached, but no backend enforcement was
|
|
174
|
+
found. This looks protected and is not.
|
|
175
|
+
- **Backend only**: enforcement exists, but no page sends a token. In BLOCK mode this can
|
|
176
|
+
reject legitimate users.
|
|
177
|
+
- **Fully integrated**: browser mode and backend path are both present. Name both.
|
|
178
|
+
|
|
179
|
+
If a script tag already exists, update it instead of adding a second one. The SDK
|
|
180
|
+
initializes from `document.currentScript`; two tags mean two configurations, and the
|
|
181
|
+
last one to run wins rather than the two merging.
|
|
182
|
+
|
|
183
|
+
## Contract check
|
|
184
|
+
|
|
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.
|
|
226
|
+
|
|
227
|
+
## Gate
|
|
228
|
+
|
|
229
|
+
The backend path is decided by the backend stack, not by browser preference. Establish
|
|
230
|
+
this before proposing edits. Discovering a backend blocker after the browser half is
|
|
231
|
+
written leaves tokens flowing with nothing enforcing them.
|
|
232
|
+
|
|
233
|
+
An integration is one backend path plus one browser mode, and they are independent
|
|
234
|
+
choices. A non-Spring-MVC backend does not rule out Seamless mode; it only rules out the
|
|
235
|
+
Spring Boot 3 starter backend path.
|
|
236
|
+
|
|
237
|
+
Backend path:
|
|
238
|
+
|
|
239
|
+
| Backend path | Requirement | Reference |
|
|
240
|
+
| --- | --- | --- |
|
|
241
|
+
| **Spring Boot 3 starter** | Spring Boot 3 with Spring MVC, and Java 17+ | `backend-spring-boot.md` |
|
|
242
|
+
| **Java core SDK** | Java 17+ | `backend-java-core.md` |
|
|
243
|
+
|
|
244
|
+
Browser mode:
|
|
245
|
+
|
|
246
|
+
| Browser mode | Use when | Reference |
|
|
247
|
+
| --- | --- | --- |
|
|
248
|
+
| **Seamless** | The page reaches the endpoint with `fetch` or async `XMLHttpRequest` | `browser-seamless.md` |
|
|
249
|
+
| **Manual** | The call needs explicit token timing, or a non-header carrier | `browser-manual.md` |
|
|
250
|
+
|
|
251
|
+
Either browser mode pairs with either backend path. The token travels in
|
|
252
|
+
`X-IntelliFend-Token` regardless. Java below 17 blocks both backend paths, and no amount
|
|
253
|
+
of browser-side work substitutes for backend enforcement.
|
|
254
|
+
|
|
255
|
+
### Run the check
|
|
256
|
+
|
|
257
|
+
Find the build file for the module that serves the protected endpoint, not the first one
|
|
258
|
+
in the tree. In a monorepo, locate the route first:
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
find . -maxdepth 4 \( -name pom.xml -o -name "build.gradle*" \) \
|
|
262
|
+
-not -path "*/node_modules/*" -not -path "*/build/*" -not -path "*/target/*"
|
|
263
|
+
rg -n "/api/register" -g "*.java" -g "*.kt" .
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
One build file, inspect it. Several, and the route cannot be tied to one of them — or
|
|
267
|
+
several backends could plausibly serve it — **stop and ask which service owns the
|
|
268
|
+
endpoint.** Two backends in a monorepo can differ in both Java version and framework, so
|
|
269
|
+
a guess here invalidates the whole integration rather than needing a tweak.
|
|
270
|
+
|
|
271
|
+
Use repo-wide build-file scans only for discovery. Do not combine a route found in one
|
|
272
|
+
module with Java or Spring evidence from another module.
|
|
273
|
+
|
|
274
|
+
#### Java target version
|
|
275
|
+
|
|
276
|
+
Read the *project's target*, never the machine's JDK.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
rg -n "maven\.compiler\.(release|source|target)|<release>|<java\.version>" <owning-pom.xml>
|
|
280
|
+
rg -n "languageVersion|sourceCompatibility|jvmToolchain|JavaVersion" <owning-build.gradle*>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
- **Maven** — `maven.compiler.release`, or the compiler plugin's `<release>`, is
|
|
284
|
+
authoritative. Spring Boot's parent POM exposes `<java.version>`, which is the
|
|
285
|
+
idiomatic place in a Boot app. **Check the parent POM too** when the module inherits;
|
|
286
|
+
the value is often not in the module's own file.
|
|
287
|
+
- **Gradle** — `java.toolchain.languageVersion = JavaLanguageVersion.of(21)` and
|
|
288
|
+
`kotlin { jvmToolchain(21) }` are both authoritative, and both easy to miss because
|
|
289
|
+
they sit inside a block rather than on a property line.
|
|
290
|
+
- **When the build file says nothing** — `.java-version`, `.sdkmanrc`, `.tool-versions`,
|
|
291
|
+
a `setup-java` step's `java-version` in `.github/workflows/`, or a JDK base image in a
|
|
292
|
+
`Dockerfile`. These are **hints, not answers**: they describe an environment, which can
|
|
293
|
+
differ from what the build compiles against. A build file that yields only hints is the
|
|
294
|
+
ambiguous row below — ask.
|
|
295
|
+
- `java -version` reports the **local** JDK. A repo targeting 11 builds fine on a machine
|
|
296
|
+
with 21 installed, so it is a last-resort hint and never evidence.
|
|
297
|
+
|
|
298
|
+
Java below 17 blocks **both** backend paths. Report the version and its source and name
|
|
299
|
+
the upgrade as the prerequisite; do not fall back to an older SDK version or write a
|
|
300
|
+
partial browser-only integration.
|
|
301
|
+
|
|
302
|
+
#### Spring Boot 3, and separately Spring MVC
|
|
303
|
+
|
|
304
|
+
Two conditions. Both must hold for the Spring Boot starter.
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
rg -n "spring-boot-starter-parent|spring-boot-dependencies|org\.springframework\.boot" \
|
|
308
|
+
<owning-pom.xml-or-build.gradle*> | rg "3\.[0-9]+"
|
|
309
|
+
rg -n "spring-boot-starter-web[\"' :<]|spring-boot-starter-webflux|spring-webmvc" \
|
|
310
|
+
<owning-pom.xml-or-build.gradle*>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Read the parent version, the `spring-boot-dependencies` BOM version, or the Gradle plugin
|
|
314
|
+
version. **Spring Boot 2.x does not qualify** — the starter is a Boot 3 artifact, so a
|
|
315
|
+
2.x app needs the core SDK path even though it is Spring.
|
|
316
|
+
|
|
317
|
+
Then MVC versus WebFlux — the trap worth checking every time:
|
|
318
|
+
|
|
319
|
+
- `spring-boot-starter-web` → Spring MVC. The starter is available when the app is also
|
|
320
|
+
Spring Boot 3 on Java 17+.
|
|
321
|
+
- `spring-boot-starter-webflux` with no `-web` → **not** Spring MVC. The starter protects
|
|
322
|
+
Spring MVC handler methods, so `@RequestShieldProtected` does not apply. Such an app is
|
|
323
|
+
Spring Boot 3 on Java 17+ and still needs the Java core SDK — say so explicitly,
|
|
324
|
+
because "Spring Boot 3, Java 21" reads like a starter green light and quietly is not.
|
|
325
|
+
Browser mode is unaffected; Seamless remains available when the request transport
|
|
326
|
+
matches.
|
|
327
|
+
- **Both present** → determine which stack serves the protected route. A
|
|
328
|
+
`@RestController` returning `Mono`/`Flux`, or a `RouterFunction`, indicates the
|
|
329
|
+
reactive path. Ask if it stays unclear.
|
|
330
|
+
|
|
331
|
+
Also not Spring MVC, and therefore the Java core SDK backend path: **Quarkus, Micronaut,
|
|
332
|
+
Dropwizard, Helidon, Ktor, Vert.x, Jakarta EE / JAX-RS on its own, and a plain servlet
|
|
333
|
+
application.**
|
|
334
|
+
|
|
335
|
+
## Then act on what you found
|
|
336
|
+
|
|
337
|
+
This decision chooses the backend path only. Pick the browser mode separately from how
|
|
338
|
+
the page issues the protected request.
|
|
339
|
+
|
|
340
|
+
| Detected | Do this |
|
|
341
|
+
| --- | --- |
|
|
342
|
+
| 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. |
|
|
343
|
+
| 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. |
|
|
344
|
+
| Java 17+ and Spring Boot 3 MVC | Both backend paths are viable. Recommend the starter and confirm once. |
|
|
345
|
+
| Ambiguous module, missing build file, version only in environment hints, or unclear MVC/WebFlux ownership | Ask, showing what you found. |
|
|
346
|
+
|
|
347
|
+
Always report the evidence with file and line references:
|
|
348
|
+
|
|
349
|
+
```text
|
|
350
|
+
Backend: theair-customer-backend/build.gradle.kts
|
|
351
|
+
Java 21 - java.toolchain.languageVersion (line 14)
|
|
352
|
+
Spring Boot 3.2.1 - org.springframework.boot plugin (line 3)
|
|
353
|
+
Spring MVC - spring-boot-starter-web (line 20)
|
|
354
|
+
Backend path: Spring Boot 3 starter. Browser mode still depends on released modes and request transport.
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Detection is inference from build files. If any line would read "unknown", ask rather
|
|
358
|
+
than assume.
|
|
359
|
+
|
|
360
|
+
## Choosing the mode
|
|
361
|
+
|
|
362
|
+
Reach this section only when **Contract check** left a genuine choice: both modes
|
|
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`.
|