@t3b/hub-guard 0.4.0 → 0.5.0
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 +2 -1
- package/dist/guard.js +1 -1
- package/dist/session.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -185,13 +185,14 @@ if (!guard.allows(r.session, "deliveries", "write")) return guard.refusePage(req
|
|
|
185
185
|
## What it enforces
|
|
186
186
|
|
|
187
187
|
- `/hub/enter?ticket=…`: an EdDSA ticket signed by the Hub's published key, for this module, from this environment's Hub, 60 seconds, single use → sets the module session (HttpOnly, Secure, SameSite=Strict) and answers a short "Opening …" page that moves on to the page (0.4.0: a SameSite=Strict cookie set on a redirect ending a navigation from another site is not sent on it). `appName` names the app on that page; `landing(path)` maps the pass's page (e.g. `"/"` → `"/app"`), never off the module's own address.
|
|
188
|
-
- Every other request: no session → 403 (HTML for browsers, JSON for APIs), on **every host** the module answers on. Idle
|
|
188
|
+
- Every other request: no session → 403 (HTML for browsers, JSON for APIs), on **every host** the module answers on. Idle 180 minutes (0.5.0), absolute 8 hours. Every 15 minutes the Hub is asked (with the app's Vercel ID) whether the person's session still stands. A Hub blip keeps the session until the next check.
|
|
189
189
|
- Open paths (`/hub/enter`, `/api/hub/manifest`, `/api/hub/health` and what you add) never need a session — they carry their own locks (the Hub's pass, a cron secret).
|
|
190
190
|
- Cloudflare Access proof checked first when the team and audience are set.
|
|
191
191
|
- `verifyRelay`, `manifestResponse`, `healthResponse`: the Hub's pass, for this module, for this purpose, from this environment's Hub; a relay also for these exact bytes and at most 5 minutes old; a call at most 60 seconds old.
|
|
192
192
|
|
|
193
193
|
## Changes
|
|
194
194
|
|
|
195
|
+
- **0.5.0** (D-062, A-509): the session's idle limit is 180 minutes (was 15); the Hub counts the 15-minute check as activity, so the person's Hub session stays alive while they work in the module.
|
|
195
196
|
- **0.4.0** (WORKFLOWS §14): page access — the pass's `pages` in the session, refreshed at every 15-minute check (`sessionCheckPages`); `guard.allows()`, `guard.refusePage()`, `pageAllowed`, `pageAccess`, `readPages`; `healthResponse(..., { pages })` sends the page list's fingerprint (`pagesFingerprint`). `enter()` answers an "Opening …" page instead of a 303 (`appName`, `landing` options; `openingPage` exported). A module on 0.3.x keeps working, but the Hub opens it for the owner only until it lists its pages.
|
|
196
197
|
- **0.3.0** (WORKFLOWS 9.3): `alert()` — report a problem to the Hub, or say it is over.
|
|
197
198
|
- **0.2.0** (8b): no module key and no pasted Hub public key. Hub → module: tokens signed by the Hub's key published at `/api/hub/jwks` (`verifyTicket`, `verifyRelay`, `verifyHubCall`, `manifestResponse`, `healthResponse`). Module → Hub: the app's own Vercel ID (`tokenBroker`, `audit`, `sessionCheck`). Removed: `signedManifest`, `relaySignature`, `importPublicKey`, the `moduleKey` / `hubPublicKeys` settings. `Guard` takes `sessionSecret`.
|
package/dist/guard.js
CHANGED
|
@@ -88,7 +88,7 @@ export class Guard {
|
|
|
88
88
|
const secret = await this.secretP;
|
|
89
89
|
const r = await readSession(cookieValue(req.headers.get("cookie"), SESSION_COOKIE), secret, nowMs, { absoluteMs: this.cfg.absoluteMs });
|
|
90
90
|
if (!r.ok) {
|
|
91
|
-
const words = { missing: "", bad: "", idle: "You were signed out after
|
|
91
|
+
const words = { missing: "", bad: "", idle: "You were signed out after 180 minutes without activity.", expired: "Your session reached its 8-hour limit." };
|
|
92
92
|
return { allow: false, response: this.refuse(req, words[r.reason] ?? "") };
|
|
93
93
|
}
|
|
94
94
|
let s = r.session;
|
package/dist/session.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { b64urlDecodeText, b64urlEncode, constantTimeEqual, hmacSha256, utf8 } from "./webcrypto.js";
|
|
2
2
|
// The module's own session (WORKFLOWS 2.2, 2.4): set at /hub/enter from a verified ticket,
|
|
3
|
-
// carried in an HttpOnly cookie signed with a key derived from the module key,
|
|
3
|
+
// carried in an HttpOnly cookie signed with a key derived from the module key, 180 minutes idle (0.5.0, A-509),
|
|
4
4
|
// 8 hours absolute for admin surfaces (a module may set shift-long for a till), re-checked with
|
|
5
5
|
// the Hub every 15 minutes.
|
|
6
6
|
export const SESSION_COOKIE = "t3b_module_session";
|
|
7
|
-
export const IDLE_MS =
|
|
7
|
+
export const IDLE_MS = 180 * 60_000;
|
|
8
8
|
export const ABSOLUTE_MS = 8 * 3_600_000;
|
|
9
9
|
export const RECHECK_MS = 15 * 60_000;
|
|
10
10
|
export async function signSession(s, secret) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t3b/hub-guard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The3Beez Hub guard: a module opens only by a Hub-signed ticket and refuses everything else. No key from the Hub: towards the Hub the app shows its own Vercel ID; from the Hub it accepts only what is signed by the key the Hub publishes. Entry route, refusal page, module session, idle rule, 15-minute re-check, Cloudflare Access proof, broker and audit clients, manifest and health answers for the Hub only. Web Crypto only: runs in Node 20+ and in edge runtimes.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|