requestshield 0.1.4 → 0.1.5
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 +211 -13
- package/package.json +16 -10
- package/skills/requestshield/SKILL.md +307 -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 +164 -164
- package/skills/requestshield/references/cli.md +183 -182
- package/skills/requestshield/references/integration-planning.md +389 -389
- package/skills/requestshield/references/troubleshooting.md +118 -118
- package/src/agent-detector.mjs +102 -74
- package/src/api-client.mjs +100 -5
- package/src/args.mjs +182 -79
- package/src/cli.mjs +255 -51
- package/src/commands/agent-setup.mjs +185 -185
- package/src/commands/apps-get.mjs +64 -0
- package/src/commands/apps-list.mjs +90 -0
- package/src/commands/billing-get.mjs +110 -0
- package/src/commands/challenge-volume.mjs +81 -0
- package/src/commands/contract.mjs +106 -0
- package/src/config.mjs +8 -0
- package/src/main.mjs +24 -24
|
@@ -1,164 +1,164 @@
|
|
|
1
|
-
# Browser SDK — Seamless mode
|
|
2
|
-
|
|
3
|
-
Seamless mode is the recommended browser integration for applications that use `fetch`
|
|
4
|
-
or asynchronous `XMLHttpRequest`. Browser SDK 1.1 matches configured application
|
|
5
|
-
endpoints and adds `X-IntelliFend-Token` automatically, so no call site changes.
|
|
6
|
-
|
|
7
|
-
Prerequisites: a public App Key, the **exact** application API endpoints to protect, and
|
|
8
|
-
backend protection configured for the corresponding operations.
|
|
9
|
-
|
|
10
|
-
## 1. Load the hosted SDK
|
|
11
|
-
|
|
12
|
-
Place the script before any application bundle that can issue a protected request —
|
|
13
|
-
otherwise an early request leaves the page before interception is installed:
|
|
14
|
-
|
|
15
|
-
```html
|
|
16
|
-
<script
|
|
17
|
-
src="SCRIPT_URL_FROM_CONTRACT"
|
|
18
|
-
data-app-key="YOUR_APP_KEY"
|
|
19
|
-
data-protect='["/api/register"]'
|
|
20
|
-
defer
|
|
21
|
-
></script>
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
`data-protect` is a **JSON array** — note the single quotes around the attribute so the
|
|
25
|
-
inner double quotes survive. Each entry is either a root-relative pathname beginning
|
|
26
|
-
with `/`, or an absolute URL without embedded credentials. Malformed JSON is a configuration
|
|
27
|
-
error — validate the attribute before shipping rather than assuming a parse failure will
|
|
28
|
-
announce itself.
|
|
29
|
-
|
|
30
|
-
Applications with a custom script loader can configure the same behaviour after the
|
|
31
|
-
hosted script loads:
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
IntelliFend.init({
|
|
35
|
-
appKey: 'YOUR_APP_KEY',
|
|
36
|
-
protect: ['/api/register'],
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Use script attributes *or* explicit initialization for initial setup, not both.
|
|
41
|
-
|
|
42
|
-
## 2. Match application endpoints exactly
|
|
43
|
-
|
|
44
|
-
RequestShield compares the **exact origin and exact pathname**. This is where a Seamless
|
|
45
|
-
install either works or quietly does nothing, so resolve it before writing the attribute:
|
|
46
|
-
|
|
47
|
-
- Query strings and fragments are ignored on both sides.
|
|
48
|
-
- **Pathname case and trailing slash are significant.**
|
|
49
|
-
- Root-relative entries resolve against the page origin.
|
|
50
|
-
- Cross-origin entries use HTTPS, except for loopback development.
|
|
51
|
-
- The same endpoint rule applies to every HTTP method.
|
|
52
|
-
|
|
53
|
-
So `/api/register` matches `/api/register?source=campaign`, but it does **not** match
|
|
54
|
-
`/api/Register` or `/api/register/`.
|
|
55
|
-
|
|
56
|
-
The practical consequence: **list the URL the application passes to `fetch` or
|
|
57
|
-
asynchronous `XMLHttpRequest`.** With a normal development proxy, the application
|
|
58
|
-
requests `/api/register` on the frontend origin. The proxy then rewrites and forwards
|
|
59
|
-
that request to an upstream route such as `https://api.example.com/register`. The
|
|
60
|
-
rewrite happens outside the browser and does not change the URL matched by Seamless.
|
|
61
|
-
Configure `/api/register`, and ensure the proxy forwards `X-IntelliFend-Token`
|
|
62
|
-
unchanged.
|
|
63
|
-
|
|
64
|
-
If the application directly requests `https://api.example.com/register`, configure
|
|
65
|
-
that absolute URL instead and configure CORS to allow the page origin, request method,
|
|
66
|
-
and `X-IntelliFend-Token`.
|
|
67
|
-
|
|
68
|
-
A redirect is different from a proxy rewrite. With an HTTP redirect, the server returns
|
|
69
|
-
a `3xx` response and the browser follows its `Location`. Seamless matches the original
|
|
70
|
-
URL passed by application code; it does not separately match the browser's internal
|
|
71
|
-
redirect request. Do not configure only the redirect destination when the application
|
|
72
|
-
initially requests `/api/register`. Avoid redirects for protected mutation endpoints
|
|
73
|
-
when possible, or verify the method, header, and CORS behavior end to end.
|
|
74
|
-
|
|
75
|
-
A path built with an ID or slug (`/api/orders/42`) has no wildcard support — list every
|
|
76
|
-
concrete path, or use Manual mode for that operation.
|
|
77
|
-
|
|
78
|
-
## 3. Send requests normally
|
|
79
|
-
|
|
80
|
-
Application code does not call `getToken()` or construct the header for a
|
|
81
|
-
Seamless-mode endpoint:
|
|
82
|
-
|
|
83
|
-
```javascript
|
|
84
|
-
const response = await fetch('/api/register', {
|
|
85
|
-
method: 'POST',
|
|
86
|
-
headers: {'Content-Type': 'application/json'},
|
|
87
|
-
body: JSON.stringify({email, password}),
|
|
88
|
-
});
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
Browser configuration controls token attachment only. Configure the corresponding
|
|
92
|
-
backend operation independently — `data-protect` creates no backend protection.
|
|
93
|
-
|
|
94
|
-
## What Seamless covers
|
|
95
|
-
|
|
96
|
-
Supported: `fetch` (string, `URL`, and `Request` inputs) and asynchronous
|
|
97
|
-
`XMLHttpRequest`.
|
|
98
|
-
|
|
99
|
-
Do not rely on Seamless and a Manual call site coexisting on the same endpoint. One
|
|
100
|
-
protected operation uses one mode — see the prerequisites in `browser-manual.md`.
|
|
101
|
-
|
|
102
|
-
## What Seamless does not cover
|
|
103
|
-
|
|
104
|
-
Any of these means the request leaves without a token, with no error — which is why
|
|
105
|
-
they are worth checking *before* choosing the mode:
|
|
106
|
-
|
|
107
|
-
- Synchronous XHR.
|
|
108
|
-
- Native form navigation (a plain `<form>` submit).
|
|
109
|
-
- `navigator.sendBeacon`.
|
|
110
|
-
- WebSocket and EventSource.
|
|
111
|
-
- Service-worker-owned requests. Web workers and server-side rendering have their own
|
|
112
|
-
global scope too — in Next.js, Nuxt, Remix and similar, confirm the protected call
|
|
113
|
-
runs in the browser.
|
|
114
|
-
- A `fetch` using `no-cors`, which cannot carry a custom header at all.
|
|
115
|
-
|
|
116
|
-
For an operation on this list, use Manual mode **only if** the application can carry the
|
|
117
|
-
token in a supported header or request-body field. Otherwise the right answer is an
|
|
118
|
-
application-specific integration agreed with IntelliFend — say that plainly rather than
|
|
119
|
-
improvising a carrier.
|
|
120
|
-
|
|
121
|
-
## Cross-origin APIs
|
|
122
|
-
|
|
123
|
-
When the protected endpoint is on another origin, its CORS response must allow the page
|
|
124
|
-
origin, the intended methods, and the `X-IntelliFend-Token` header. Missing that header
|
|
125
|
-
in `Access-Control-Allow-Headers` means the browser strips it and every request reads as
|
|
126
|
-
missing a token.
|
|
127
|
-
|
|
128
|
-
## Verifying Seamless
|
|
129
|
-
|
|
130
|
-
Static checks:
|
|
131
|
-
|
|
132
|
-
1. Exactly one script tag, loaded before application bundles, with valid JSON in
|
|
133
|
-
`data-protect`.
|
|
134
|
-
2. Every listed entry matches a URL the browser actually requests — origin, case, and
|
|
135
|
-
trailing slash included.
|
|
136
|
-
3. Every protected endpoint reaches the network via `fetch` or async XHR from page
|
|
137
|
-
scope.
|
|
138
|
-
|
|
139
|
-
Runtime check: exercise the endpoint, confirm the network request carries a non-empty
|
|
140
|
-
`X-IntelliFend-Token`, then confirm the platform saw it. This proves the browser half is
|
|
141
|
-
firing; the negative test in `SKILL.md` proves backend enforcement.
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
requestshield challenge volume <app-key> \
|
|
145
|
-
--from <start> \
|
|
146
|
-
--to <end> \
|
|
147
|
-
--granularity hour
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Zero volume with a correct-looking `data-protect` is nearly always a path mismatch
|
|
151
|
-
(trailing slash, case, a different origin than assumed) or one of the uncovered
|
|
152
|
-
transports above. Re-read the actual request URL before changing anything else.
|
|
153
|
-
|
|
154
|
-
## Expected result
|
|
155
|
-
|
|
156
|
-
Matching requests carry one non-empty `X-IntelliFend-Token` header; requests outside the
|
|
157
|
-
configured list are unchanged.
|
|
158
|
-
|
|
159
|
-
## CSP and token handling
|
|
160
|
-
|
|
161
|
-
Identical to Manual mode — see the CSP and token-handling sections of
|
|
162
|
-
`browser-manual.md`. The `worker-src 'self' blob:` directive matters just as much here:
|
|
163
|
-
without it, every intercepted request attaches an empty token and the backend blocks
|
|
164
|
-
traffic that looks correctly integrated.
|
|
1
|
+
# Browser SDK — Seamless mode
|
|
2
|
+
|
|
3
|
+
Seamless mode is the recommended browser integration for applications that use `fetch`
|
|
4
|
+
or asynchronous `XMLHttpRequest`. Browser SDK 1.1 matches configured application
|
|
5
|
+
endpoints and adds `X-IntelliFend-Token` automatically, so no call site changes.
|
|
6
|
+
|
|
7
|
+
Prerequisites: a public App Key, the **exact** application API endpoints to protect, and
|
|
8
|
+
backend protection configured for the corresponding operations.
|
|
9
|
+
|
|
10
|
+
## 1. Load the hosted SDK
|
|
11
|
+
|
|
12
|
+
Place the script before any application bundle that can issue a protected request —
|
|
13
|
+
otherwise an early request leaves the page before interception is installed:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<script
|
|
17
|
+
src="SCRIPT_URL_FROM_CONTRACT"
|
|
18
|
+
data-app-key="YOUR_APP_KEY"
|
|
19
|
+
data-protect='["/api/register"]'
|
|
20
|
+
defer
|
|
21
|
+
></script>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`data-protect` is a **JSON array** — note the single quotes around the attribute so the
|
|
25
|
+
inner double quotes survive. Each entry is either a root-relative pathname beginning
|
|
26
|
+
with `/`, or an absolute URL without embedded credentials. Malformed JSON is a configuration
|
|
27
|
+
error — validate the attribute before shipping rather than assuming a parse failure will
|
|
28
|
+
announce itself.
|
|
29
|
+
|
|
30
|
+
Applications with a custom script loader can configure the same behaviour after the
|
|
31
|
+
hosted script loads:
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
IntelliFend.init({
|
|
35
|
+
appKey: 'YOUR_APP_KEY',
|
|
36
|
+
protect: ['/api/register'],
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Use script attributes *or* explicit initialization for initial setup, not both.
|
|
41
|
+
|
|
42
|
+
## 2. Match application endpoints exactly
|
|
43
|
+
|
|
44
|
+
RequestShield compares the **exact origin and exact pathname**. This is where a Seamless
|
|
45
|
+
install either works or quietly does nothing, so resolve it before writing the attribute:
|
|
46
|
+
|
|
47
|
+
- Query strings and fragments are ignored on both sides.
|
|
48
|
+
- **Pathname case and trailing slash are significant.**
|
|
49
|
+
- Root-relative entries resolve against the page origin.
|
|
50
|
+
- Cross-origin entries use HTTPS, except for loopback development.
|
|
51
|
+
- The same endpoint rule applies to every HTTP method.
|
|
52
|
+
|
|
53
|
+
So `/api/register` matches `/api/register?source=campaign`, but it does **not** match
|
|
54
|
+
`/api/Register` or `/api/register/`.
|
|
55
|
+
|
|
56
|
+
The practical consequence: **list the URL the application passes to `fetch` or
|
|
57
|
+
asynchronous `XMLHttpRequest`.** With a normal development proxy, the application
|
|
58
|
+
requests `/api/register` on the frontend origin. The proxy then rewrites and forwards
|
|
59
|
+
that request to an upstream route such as `https://api.example.com/register`. The
|
|
60
|
+
rewrite happens outside the browser and does not change the URL matched by Seamless.
|
|
61
|
+
Configure `/api/register`, and ensure the proxy forwards `X-IntelliFend-Token`
|
|
62
|
+
unchanged.
|
|
63
|
+
|
|
64
|
+
If the application directly requests `https://api.example.com/register`, configure
|
|
65
|
+
that absolute URL instead and configure CORS to allow the page origin, request method,
|
|
66
|
+
and `X-IntelliFend-Token`.
|
|
67
|
+
|
|
68
|
+
A redirect is different from a proxy rewrite. With an HTTP redirect, the server returns
|
|
69
|
+
a `3xx` response and the browser follows its `Location`. Seamless matches the original
|
|
70
|
+
URL passed by application code; it does not separately match the browser's internal
|
|
71
|
+
redirect request. Do not configure only the redirect destination when the application
|
|
72
|
+
initially requests `/api/register`. Avoid redirects for protected mutation endpoints
|
|
73
|
+
when possible, or verify the method, header, and CORS behavior end to end.
|
|
74
|
+
|
|
75
|
+
A path built with an ID or slug (`/api/orders/42`) has no wildcard support — list every
|
|
76
|
+
concrete path, or use Manual mode for that operation.
|
|
77
|
+
|
|
78
|
+
## 3. Send requests normally
|
|
79
|
+
|
|
80
|
+
Application code does not call `getToken()` or construct the header for a
|
|
81
|
+
Seamless-mode endpoint:
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
const response = await fetch('/api/register', {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {'Content-Type': 'application/json'},
|
|
87
|
+
body: JSON.stringify({email, password}),
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Browser configuration controls token attachment only. Configure the corresponding
|
|
92
|
+
backend operation independently — `data-protect` creates no backend protection.
|
|
93
|
+
|
|
94
|
+
## What Seamless covers
|
|
95
|
+
|
|
96
|
+
Supported: `fetch` (string, `URL`, and `Request` inputs) and asynchronous
|
|
97
|
+
`XMLHttpRequest`.
|
|
98
|
+
|
|
99
|
+
Do not rely on Seamless and a Manual call site coexisting on the same endpoint. One
|
|
100
|
+
protected operation uses one mode — see the prerequisites in `browser-manual.md`.
|
|
101
|
+
|
|
102
|
+
## What Seamless does not cover
|
|
103
|
+
|
|
104
|
+
Any of these means the request leaves without a token, with no error — which is why
|
|
105
|
+
they are worth checking *before* choosing the mode:
|
|
106
|
+
|
|
107
|
+
- Synchronous XHR.
|
|
108
|
+
- Native form navigation (a plain `<form>` submit).
|
|
109
|
+
- `navigator.sendBeacon`.
|
|
110
|
+
- WebSocket and EventSource.
|
|
111
|
+
- Service-worker-owned requests. Web workers and server-side rendering have their own
|
|
112
|
+
global scope too — in Next.js, Nuxt, Remix and similar, confirm the protected call
|
|
113
|
+
runs in the browser.
|
|
114
|
+
- A `fetch` using `no-cors`, which cannot carry a custom header at all.
|
|
115
|
+
|
|
116
|
+
For an operation on this list, use Manual mode **only if** the application can carry the
|
|
117
|
+
token in a supported header or request-body field. Otherwise the right answer is an
|
|
118
|
+
application-specific integration agreed with IntelliFend — say that plainly rather than
|
|
119
|
+
improvising a carrier.
|
|
120
|
+
|
|
121
|
+
## Cross-origin APIs
|
|
122
|
+
|
|
123
|
+
When the protected endpoint is on another origin, its CORS response must allow the page
|
|
124
|
+
origin, the intended methods, and the `X-IntelliFend-Token` header. Missing that header
|
|
125
|
+
in `Access-Control-Allow-Headers` means the browser strips it and every request reads as
|
|
126
|
+
missing a token.
|
|
127
|
+
|
|
128
|
+
## Verifying Seamless
|
|
129
|
+
|
|
130
|
+
Static checks:
|
|
131
|
+
|
|
132
|
+
1. Exactly one script tag, loaded before application bundles, with valid JSON in
|
|
133
|
+
`data-protect`.
|
|
134
|
+
2. Every listed entry matches a URL the browser actually requests — origin, case, and
|
|
135
|
+
trailing slash included.
|
|
136
|
+
3. Every protected endpoint reaches the network via `fetch` or async XHR from page
|
|
137
|
+
scope.
|
|
138
|
+
|
|
139
|
+
Runtime check: exercise the endpoint, confirm the network request carries a non-empty
|
|
140
|
+
`X-IntelliFend-Token`, then confirm the platform saw it. This proves the browser half is
|
|
141
|
+
firing; the negative test in `SKILL.md` proves backend enforcement.
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
requestshield challenge volume <app-key> \
|
|
145
|
+
--from <start> \
|
|
146
|
+
--to <end> \
|
|
147
|
+
--granularity hour
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Zero volume with a correct-looking `data-protect` is nearly always a path mismatch
|
|
151
|
+
(trailing slash, case, a different origin than assumed) or one of the uncovered
|
|
152
|
+
transports above. Re-read the actual request URL before changing anything else.
|
|
153
|
+
|
|
154
|
+
## Expected result
|
|
155
|
+
|
|
156
|
+
Matching requests carry one non-empty `X-IntelliFend-Token` header; requests outside the
|
|
157
|
+
configured list are unchanged.
|
|
158
|
+
|
|
159
|
+
## CSP and token handling
|
|
160
|
+
|
|
161
|
+
Identical to Manual mode — see the CSP and token-handling sections of
|
|
162
|
+
`browser-manual.md`. The `worker-src 'self' blob:` directive matters just as much here:
|
|
163
|
+
without it, every intercepted request attaches an empty token and the backend blocks
|
|
164
|
+
traffic that looks correctly integrated.
|