@consciousclouds/access 0.1.1 → 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/CHANGELOG.md +41 -0
- package/dist/client/index.d.ts +10 -10
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +104 -18
- package/dist/client/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/server/index.d.ts +37 -5
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +87 -8
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@consciousclouds/access` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.1.3 (unreleased)
|
|
6
|
+
|
|
7
|
+
Three seams CCU Admin hand-rolled around (Lane 11's F0 audit, S1–S3). Types and thin wrappers only; the Control Plane
|
|
8
|
+
decides.
|
|
9
|
+
|
|
10
|
+
- **S1, unreachable is not denied (behaviour change, fail-closed preserved):** `can()` (client and server) answers
|
|
11
|
+
`unknown` when the Control Plane is unreachable, answers 5xx, or answers a 200 that does not say
|
|
12
|
+
`allowed: true|false`. A 4xx is still `denied`, except 408 and 429, which say "not now" and are `unknown`. Only `allowed` allows, so a caller gating on `=== 'allowed'` (every
|
|
13
|
+
consumer in this repository at the time of this release) is unchanged. A candidate the Control Plane could not answer
|
|
14
|
+
is still not granted by the Operator session read.
|
|
15
|
+
- **S2, the Operator session lifecycle:**
|
|
16
|
+
- client `revoke(token)` returns the outcome, `revoked | failed | unknown | absent`. `logout(token)` keeps its 0.1.2
|
|
17
|
+
contract exactly (it resolves on any answer and throws only when there is none), because CCU Admin's logout route
|
|
18
|
+
relies on that throw to answer LOGOUT_UNCONFIRMED;
|
|
19
|
+
- server `refresh(req)` reads the new `refreshCookieName` and returns `{ok: true, tokens}` or
|
|
20
|
+
`{ok: false, reason: 'absent' | 'rejected' | 'unavailable'}`;
|
|
21
|
+
- server `logout(req)` returns the outcome;
|
|
22
|
+
- `sessionCookies(tokens, opts)` and `clearedSessionCookies(opts)` build the Set-Cookie values: HttpOnly always,
|
|
23
|
+
Secure and SameSite=Lax by default, the access Max-Age from `expiresIn`, and invalid names or paths refused.
|
|
24
|
+
- **S3, a verified, LIVE identity:** client `me(token)` and server `whoami(req)` return a `VerifiedOperator` only when
|
|
25
|
+
`GET /operator/me` answers 200 for the token's own `sub` AND the Operator session read answers `live: true` for its
|
|
26
|
+
(`sub`, `sid`), which the Control Plane says only for an active operator whose Operator session is not revoked or
|
|
27
|
+
expired. Any failure is `null`, never the token's unverified claims. It means "signed in at that moment", never
|
|
28
|
+
authority: that comes only from `can()`. The display `whoami(token)` on the client is unchanged.
|
|
29
|
+
- **New root types:** `VerifiedOperator`, `LogoutOutcome`, `RefreshOutcome`, `TokenSetShape` (the client's `TokenSet`
|
|
30
|
+
is now its alias).
|
|
31
|
+
|
|
32
|
+
## 0.1.2
|
|
33
|
+
|
|
34
|
+
- No API change. Republished so that the bytes on the registry reproduce from the committed tree and are
|
|
35
|
+
pinned by the published-byte digest gate (`scripts/sdk_packed_digest.py`). 0.1.1's immutable bytes differ
|
|
36
|
+
from the source that followed it by one comment, which no gate could see because no digest was recorded;
|
|
37
|
+
from this release the packed contents are pinned per version and CI refuses a source change that would
|
|
38
|
+
diverge from what was published.
|
|
39
|
+
|
|
40
|
+
## 0.1.1
|
|
41
|
+
|
|
42
|
+
- Fail-closed repair: `decodeURIComponent` sat outside every guard, so a malformed cookie threw `URIError` out
|
|
43
|
+
of every server-side entry point instead of denying. Packaging repair: the `capability-sdk` dependency was
|
|
44
|
+
`workspace:*`, which would have shipped an uninstallable tarball. No API change.
|
|
45
|
+
|
|
5
46
|
## 0.1.0
|
|
6
47
|
|
|
7
48
|
- Initial release. The policy-free Access SDK for the Control Plane's operator
|
package/dist/client/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* never holds the operator token (it lives in an httpOnly cookie); browser code
|
|
10
10
|
* goes through the product's same-origin BFF routes and the `/react` hooks.
|
|
11
11
|
*/
|
|
12
|
-
import type { AccessDecision, AccessIntent, AccessSession, Grant, OperatorIdentity, ProjectScope } from '../types.js';
|
|
12
|
+
import type { AccessDecision, AccessIntent, AccessSession, Grant, LogoutOutcome, OperatorIdentity, ProjectScope, TokenSetShape, VerifiedOperator } from '../types.js';
|
|
13
13
|
/** Configuration for a client bound to one Control Plane origin. */
|
|
14
14
|
export interface AccessClientConfig {
|
|
15
15
|
/** The Control Plane base URL (server-only; never a `NEXT_PUBLIC_` value). */
|
|
@@ -25,15 +25,7 @@ export interface LoginInput {
|
|
|
25
25
|
password: string;
|
|
26
26
|
}
|
|
27
27
|
/** The token bundle the Control Plane returns from login/refresh (snake_case wire → camelCase). */
|
|
28
|
-
export
|
|
29
|
-
accessToken: string;
|
|
30
|
-
refreshToken: string;
|
|
31
|
-
sid: string;
|
|
32
|
-
operatorId: string;
|
|
33
|
-
/** Access-token lifetime in seconds (~15m). */
|
|
34
|
-
expiresIn: number;
|
|
35
|
-
tokenType: string;
|
|
36
|
-
}
|
|
28
|
+
export type TokenSet = TokenSetShape;
|
|
37
29
|
/** An error carrying the HTTP status so callers can distinguish 401 from unreachable. */
|
|
38
30
|
export declare class AccessError extends Error {
|
|
39
31
|
readonly status: number;
|
|
@@ -46,8 +38,16 @@ export declare function identityFromToken(token: string | null | undefined): Ope
|
|
|
46
38
|
export interface AccessClient {
|
|
47
39
|
login(input: LoginInput): Promise<TokenSet>;
|
|
48
40
|
refresh(refreshToken: string): Promise<TokenSet>;
|
|
41
|
+
/** Revoke the Operator session bound to `token` (0.1.2 semantics, unchanged: resolves on any answer, throws only when
|
|
42
|
+
* there is none). Prefer `revoke`, whose outcome says whether it landed. */
|
|
49
43
|
logout(token: string): Promise<void>;
|
|
44
|
+
/** Revoke the Operator session bound to `token`, and say whether it landed (S2). */
|
|
45
|
+
revoke(token: string): Promise<LogoutOutcome>;
|
|
46
|
+
/** The DISPLAY identity: the token's claims, enriched by `/operator/me` when it answers. Unverified by design. */
|
|
50
47
|
whoami(token: string): Promise<OperatorIdentity | null>;
|
|
48
|
+
/** The VERIFIED, LIVE operator (S3): `/operator/me` for the token's operator AND the Operator session read live for its sid;
|
|
49
|
+
* otherwise null. Never falls back to the token's unverified claims. Authority still comes only from `can()`. */
|
|
50
|
+
me(token: string): Promise<VerifiedOperator | null>;
|
|
51
51
|
session(token: string, scope: ProjectScope, candidates?: readonly Grant[]): Promise<AccessSession>;
|
|
52
52
|
can(token: string, scope: ProjectScope, action: Grant, intent?: AccessIntent): Promise<AccessDecision>;
|
|
53
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,KAAK,EACL,gBAAgB,EAChB,YAAY,EACb,MAAM,aAAa,CAAC;AAErB,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mGAAmG;AACnG,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB,oEAAoE;AACpE,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mGAAmG;AACnG,MAAM,MAAM,QAAQ,GAAG,aAAa,CAAC;AAErC,yFAAyF;AACzF,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBACX,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAM3D;AAkCD,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,GAAG,IAAI,CAW3F;AAuBD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD;gFAC4E;IAC5E,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,oFAAoF;IACpF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9C,kHAAkH;IAClH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACxD;qHACiH;IACjH,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,SAAS,KAAK,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACnG,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACxG;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAsM3E"}
|
package/dist/client/index.js
CHANGED
|
@@ -36,6 +36,13 @@ function decodeClaims(token) {
|
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether a non-2xx answer is the Control Plane REFUSING (a definite no): a 4xx, except 408 and 429, which say "not
|
|
41
|
+
* now", and are treated like no answer (Lane 4's advisory (a)).
|
|
42
|
+
*/
|
|
43
|
+
function refused(status) {
|
|
44
|
+
return status >= 400 && status < 500 && status !== 408 && status !== 429;
|
|
45
|
+
}
|
|
39
46
|
function str(v) {
|
|
40
47
|
return typeof v === 'string' ? v : '';
|
|
41
48
|
}
|
|
@@ -64,6 +71,11 @@ export function createAccessClient(config) {
|
|
|
64
71
|
const doFetch = config.fetchImpl ?? fetch;
|
|
65
72
|
const base = config.baseUrl.replace(/\/$/, '');
|
|
66
73
|
const ttlSeconds = config.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
74
|
+
/** The Operator session read's URL, for (sub, sid) and, when given, a project. One place builds it. */
|
|
75
|
+
function sessionReadUrl(sub, sid, project) {
|
|
76
|
+
const q = `operator_sub=${encodeURIComponent(sub)}&sid=${encodeURIComponent(sid)}`;
|
|
77
|
+
return `${base}/access/session?${q}${project === undefined ? '' : `&project=${encodeURIComponent(project)}`}`;
|
|
78
|
+
}
|
|
67
79
|
function tokenSetFrom(body) {
|
|
68
80
|
return {
|
|
69
81
|
accessToken: str(body.access_token),
|
|
@@ -105,6 +117,24 @@ export function createAccessClient(config) {
|
|
|
105
117
|
cache: 'no-store',
|
|
106
118
|
});
|
|
107
119
|
}
|
|
120
|
+
async function revoke(token) {
|
|
121
|
+
if (!token)
|
|
122
|
+
return 'absent';
|
|
123
|
+
let res;
|
|
124
|
+
try {
|
|
125
|
+
res = await doFetch(`${base}/operator/logout`, {
|
|
126
|
+
method: 'POST',
|
|
127
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
128
|
+
cache: 'no-store',
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return 'unknown'; // no answer: the request may have landed
|
|
133
|
+
}
|
|
134
|
+
if (res.ok)
|
|
135
|
+
return 'revoked';
|
|
136
|
+
return refused(res.status) ? 'failed' : 'unknown';
|
|
137
|
+
}
|
|
108
138
|
async function whoami(token) {
|
|
109
139
|
const fromToken = identityFromToken(token);
|
|
110
140
|
if (!fromToken)
|
|
@@ -122,28 +152,84 @@ export function createAccessClient(config) {
|
|
|
122
152
|
displayName: str(body.display_name) || undefined,
|
|
123
153
|
};
|
|
124
154
|
}
|
|
155
|
+
async function me(token) {
|
|
156
|
+
const claims = token ? decodeClaims(token) : null;
|
|
157
|
+
const sub = str(claims?.sub);
|
|
158
|
+
const sid = str(claims?.sid);
|
|
159
|
+
if (!claims || !sub || !sid)
|
|
160
|
+
return null;
|
|
161
|
+
// TWO uncached reads, both required (Lane 4, S3): the profile, for THIS token's operator; and the Operator session
|
|
162
|
+
// read, whose `live` is the Control Plane's own liveness of (sub, sid) for an active operator. The token's
|
|
163
|
+
// signature alone outlives a revoked sid by up to its ~15m lifetime, so a profile alone is not "signed in".
|
|
164
|
+
const headers = { Authorization: `Bearer ${token}` };
|
|
165
|
+
let profile, live;
|
|
166
|
+
try {
|
|
167
|
+
[profile, live] = await Promise.all([
|
|
168
|
+
doFetch(`${base}/operator/me`, { headers, cache: 'no-store' }),
|
|
169
|
+
doFetch(sessionReadUrl(sub, sid), {
|
|
170
|
+
headers,
|
|
171
|
+
cache: 'no-store',
|
|
172
|
+
}),
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
if (profile.status !== 200 || live.status !== 200)
|
|
179
|
+
return null;
|
|
180
|
+
const [body, liveness] = (await Promise.all([
|
|
181
|
+
profile.json().catch(() => null),
|
|
182
|
+
live.json().catch(() => null),
|
|
183
|
+
]));
|
|
184
|
+
// The Control Plane answered for THIS token's operator, and says its Operator session is live; otherwise not.
|
|
185
|
+
if (!body || str(body.operator_id) !== sub)
|
|
186
|
+
return null;
|
|
187
|
+
if (liveness?.live !== true)
|
|
188
|
+
return null;
|
|
189
|
+
return {
|
|
190
|
+
sub,
|
|
191
|
+
email: str(body.email),
|
|
192
|
+
displayName: str(body.display_name) || undefined,
|
|
193
|
+
status: str(body.status),
|
|
194
|
+
sid,
|
|
195
|
+
iss: str(claims.iss),
|
|
196
|
+
aud: str(claims.aud),
|
|
197
|
+
exp: typeof claims.exp === 'number' ? claims.exp : undefined,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
125
200
|
async function can(token, scope, action, intent = 'mutate') {
|
|
126
201
|
const { sub, sid } = principalFromToken(token);
|
|
127
202
|
if (!sub || !sid)
|
|
128
203
|
return 'denied';
|
|
129
204
|
// Send the bearer so an edge-authed ingress (the Operator Gateway) verifies the operator; the
|
|
130
205
|
// (operator_sub, sid) body stays the Control Plane's S2S proof (defense in depth — the CP re-proves).
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
206
|
+
// UNREACHABLE IS NOT DENIED (0.1.3, S1). A 4xx is the Control Plane refusing: `denied`. No answer, a 5xx, or a 200
|
|
207
|
+
// that does not say `allowed: true|false` is a question it did not answer: `unknown`. Both fail closed for a caller
|
|
208
|
+
// that gates on `=== 'allowed'`; `unknown` lets it say "unavailable" instead of "you may not".
|
|
209
|
+
let res;
|
|
210
|
+
try {
|
|
211
|
+
res = await doFetch(`${base}/access/authorize`, {
|
|
212
|
+
method: 'POST',
|
|
213
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
|
|
214
|
+
body: JSON.stringify({
|
|
215
|
+
operator_sub: sub,
|
|
216
|
+
sid,
|
|
217
|
+
action,
|
|
218
|
+
project: scope.project,
|
|
219
|
+
intent,
|
|
220
|
+
}),
|
|
221
|
+
cache: 'no-store',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return 'unknown';
|
|
226
|
+
}
|
|
143
227
|
if (!res.ok)
|
|
144
|
-
return 'denied';
|
|
145
|
-
const body = (await res.json().catch(() =>
|
|
146
|
-
|
|
228
|
+
return refused(res.status) ? 'denied' : 'unknown';
|
|
229
|
+
const body = (await res.json().catch(() => null));
|
|
230
|
+
if (body?.allowed === true)
|
|
231
|
+
return 'allowed';
|
|
232
|
+
return body?.allowed === false ? 'denied' : 'unknown';
|
|
147
233
|
}
|
|
148
234
|
async function session(token, scope, candidates = []) {
|
|
149
235
|
const identity = identityFromToken(token);
|
|
@@ -151,7 +237,7 @@ export function createAccessClient(config) {
|
|
|
151
237
|
const { sub, sid } = principalFromToken(token);
|
|
152
238
|
if (!sub || !sid)
|
|
153
239
|
return empty;
|
|
154
|
-
const url =
|
|
240
|
+
const url = sessionReadUrl(sub, sid, scope.project);
|
|
155
241
|
// Bearer for the edge-authed ingress; the (operator_sub, sid) query stays the CP's S2S proof.
|
|
156
242
|
const res = await doFetch(url, { cache: 'no-store', headers: { Authorization: `Bearer ${token}` } });
|
|
157
243
|
if (!res.ok)
|
|
@@ -167,12 +253,12 @@ export function createAccessClient(config) {
|
|
|
167
253
|
// probe with `read` so a read-only operator's read capabilities resolve.
|
|
168
254
|
const grants = [];
|
|
169
255
|
for (const action of candidates) {
|
|
170
|
-
const decision = await can(token, scope, action, 'read').catch(() => '
|
|
256
|
+
const decision = await can(token, scope, action, 'read').catch(() => 'unknown');
|
|
171
257
|
if (decision === 'allowed')
|
|
172
258
|
grants.push(action);
|
|
173
259
|
}
|
|
174
260
|
return { identity, scope, roles, grants, ttlSeconds };
|
|
175
261
|
}
|
|
176
|
-
return { login, refresh, logout, whoami, session, can };
|
|
262
|
+
return { login, refresh, logout, revoke, whoami, me, session, can };
|
|
177
263
|
}
|
|
178
264
|
//# sourceMappingURL=index.js.map
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,5 +11,5 @@
|
|
|
11
11
|
* Control Plane (control-plane-doctrine §5); the SDK only asks the five
|
|
12
12
|
* operating questions and enforces the answers, fail-closed.
|
|
13
13
|
*/
|
|
14
|
-
export type { OperatorIdentity, ProjectScope, Grant, AccessDecision, AccessIntent, AccessSession, PermissionResolver, } from './types.js';
|
|
14
|
+
export type { OperatorIdentity, ProjectScope, Grant, AccessDecision, AccessIntent, AccessSession, PermissionResolver, VerifiedOperator, LogoutOutcome, RefreshOutcome, TokenSetShape, } from './types.js';
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,KAAK,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* token never reach the browser.
|
|
6
6
|
*
|
|
7
7
|
* FAIL-CLOSED by construction — this is the load-bearing enforcement seam
|
|
8
|
-
* (control-plane-doctrine §4):
|
|
9
|
-
*
|
|
10
|
-
* access. Carries NO policy: it forwards the operator's identity to the Control
|
|
8
|
+
* (control-plane-doctrine §4): a deny resolves to `denied`, an unreachable or
|
|
9
|
+
* erroring Control Plane to `unknown` (0.1.3: distinguishable, never `allowed`),
|
|
10
|
+
* and an empty Operator session on any failure. A failure can never widen access. Carries NO policy: it forwards the operator's identity to the Control
|
|
11
11
|
* Plane, which decides.
|
|
12
12
|
*/
|
|
13
|
-
import type { AccessDecision, AccessIntent, AccessSession, Grant, OperatorIdentity, ProjectScope } from '../types.js';
|
|
13
|
+
import type { AccessDecision, AccessIntent, AccessSession, Grant, LogoutOutcome, OperatorIdentity, ProjectScope, RefreshOutcome, TokenSetShape, VerifiedOperator } from '../types.js';
|
|
14
14
|
/** The minimum request shape the adapter needs — satisfied by a Fetch `Request`
|
|
15
15
|
* or `{ headers: <Next headers()> }`. */
|
|
16
16
|
export interface RequestLike {
|
|
@@ -24,6 +24,8 @@ export interface ServerAccessConfig {
|
|
|
24
24
|
baseUrl: string;
|
|
25
25
|
/** The httpOnly cookie carrying the operator token (e.g. `ccu_operator`). */
|
|
26
26
|
cookieName: string;
|
|
27
|
+
/** The httpOnly cookie carrying the refresh token. Without it, `refresh()` answers `absent`. */
|
|
28
|
+
refreshCookieName?: string;
|
|
27
29
|
/** The default project scope for this surface (single-project surfaces set it once). */
|
|
28
30
|
scope?: ProjectScope;
|
|
29
31
|
/** The capability candidates whose granted subset seeds `AccessSession.grants`
|
|
@@ -42,9 +44,39 @@ export interface ServerAccess {
|
|
|
42
44
|
scope(req?: RequestLike): ProjectScope;
|
|
43
45
|
/** What permissions does the operator have here? (fail-closed empty session on any failure). */
|
|
44
46
|
session(req: RequestLike, scope?: ProjectScope): Promise<AccessSession>;
|
|
45
|
-
/** Can this action be performed?
|
|
47
|
+
/** Can this action be performed? Uncached and fail-closed: a deny is `denied`, an unreachable Control Plane or a
|
|
48
|
+
* throw is `unknown` (0.1.3). Only `allowed` allows. */
|
|
46
49
|
can(req: RequestLike, scope: ProjectScope, action: Grant, intent?: AccessIntent): Promise<AccessDecision>;
|
|
50
|
+
/** Who is the operator, as the Control Plane accepts them NOW? (S3: the profile and a live Operator session; null on
|
|
51
|
+
* any failure, never the cookie's unverified claims; see VerifiedOperator for what it proves.) */
|
|
52
|
+
whoami(req: RequestLike): Promise<VerifiedOperator | null>;
|
|
53
|
+
/** Rotate the Operator session from the refresh cookie (S2). The caller sets the new cookies (`sessionCookies`). */
|
|
54
|
+
refresh(req: RequestLike): Promise<RefreshOutcome>;
|
|
55
|
+
/** Revoke the Operator session bound to the operator cookie (S2). Only `revoked` means revoked. */
|
|
56
|
+
logout(req: RequestLike): Promise<LogoutOutcome>;
|
|
47
57
|
}
|
|
48
58
|
/** Create the request-bound BFF adapter. */
|
|
49
59
|
export declare function createAccess(config: ServerAccessConfig): ServerAccess;
|
|
60
|
+
export interface SessionCookieOptions {
|
|
61
|
+
/** The operator-token cookie (the same name `createAccess` reads). */
|
|
62
|
+
cookieName: string;
|
|
63
|
+
/** The refresh-token cookie. Absent ⇒ no refresh cookie is written. */
|
|
64
|
+
refreshCookieName?: string;
|
|
65
|
+
/** Default `/`. */
|
|
66
|
+
path?: string;
|
|
67
|
+
/** The refresh cookie's path (default: `path`), so it can be scoped to the refresh route alone. */
|
|
68
|
+
refreshPath?: string;
|
|
69
|
+
/** Default `true`. Turn off only for a plain-http development origin. */
|
|
70
|
+
secure?: boolean;
|
|
71
|
+
/** Default `Lax`. */
|
|
72
|
+
sameSite?: 'Lax' | 'Strict';
|
|
73
|
+
/** The access cookie's Max-Age in seconds (default: the TokenSet's `expiresIn`). */
|
|
74
|
+
maxAgeSeconds?: number;
|
|
75
|
+
/** The refresh cookie's Max-Age in seconds. Absent ⇒ it lasts for the browser's lifetime. */
|
|
76
|
+
refreshMaxAgeSeconds?: number;
|
|
77
|
+
}
|
|
78
|
+
/** The Set-Cookie values that bind `tokens` to the browser: the access cookie, then the refresh cookie when named. */
|
|
79
|
+
export declare function sessionCookies(tokens: TokenSetShape, o: SessionCookieOptions): string[];
|
|
80
|
+
/** The Set-Cookie values that clear the Operator session's cookies (Max-Age=0, same names and paths). */
|
|
81
|
+
export declare function clearedSessionCookies(o: SessionCookieOptions): string[];
|
|
50
82
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,KAAK,EACL,gBAAgB,EAChB,YAAY,EACb,MAAM,aAAa,CAAC;AAErB;yCACyC;AACzC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/C;AAED,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,wFAAwF;IACxF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;iGAC6F;IAC7F,YAAY,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IAChC,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACpD,oDAAoD;IACpD,KAAK,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC;IACvC,gGAAgG;IAChG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACxE
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAErB;yCACyC;AACzC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAC/C;AAED,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB;iGAC6F;IAC7F,YAAY,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IAChC,qCAAqC;IACrC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,4FAA4F;IAC5F,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,gBAAgB,GAAG,IAAI,CAAC;IACpD,oDAAoD;IACpD,KAAK,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,YAAY,CAAC;IACvC,gGAAgG;IAChG,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACxE;4DACwD;IACxD,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1G;sGACkG;IAClG,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC3D,oHAAoH;IACpH,OAAO,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACnD,mGAAmG;IACnG,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAClD;AA6BD,4CAA4C;AAC5C,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,YAAY,CAyFrE;AAaD,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mGAAmG;IACnG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC5B,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6FAA6F;IAC7F,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAeD,sHAAsH;AACtH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE,CASvF;AAED,yGAAyG;AACzG,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAKvE"}
|
package/dist/server/index.js
CHANGED
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
* token never reach the browser.
|
|
6
6
|
*
|
|
7
7
|
* FAIL-CLOSED by construction — this is the load-bearing enforcement seam
|
|
8
|
-
* (control-plane-doctrine §4):
|
|
9
|
-
*
|
|
10
|
-
* access. Carries NO policy: it forwards the operator's identity to the Control
|
|
8
|
+
* (control-plane-doctrine §4): a deny resolves to `denied`, an unreachable or
|
|
9
|
+
* erroring Control Plane to `unknown` (0.1.3: distinguishable, never `allowed`),
|
|
10
|
+
* and an empty Operator session on any failure. A failure can never widen access. Carries NO policy: it forwards the operator's identity to the Control
|
|
11
11
|
* Plane, which decides.
|
|
12
12
|
*/
|
|
13
|
-
import { createAccessClient, identityFromToken } from '../client/index.js';
|
|
13
|
+
import { AccessError, createAccessClient, identityFromToken } from '../client/index.js';
|
|
14
14
|
const EMPTY_SCOPE = { project: '', environment: '' };
|
|
15
15
|
/**
|
|
16
16
|
* Pull one cookie value out of a raw `Cookie:` header.
|
|
17
17
|
*
|
|
18
18
|
* FAIL-CLOSED ON A MALFORMED VALUE. `decodeURIComponent` THROWS a URIError on an invalid percent-escape, and a
|
|
19
|
-
* cookie header is attacker-influenced input: a request carrying `cc=%` made
|
|
20
|
-
*
|
|
19
|
+
* cookie header is attacker-influenced input: a request carrying `cc=%` made every entry point below throw
|
|
20
|
+
* rather than deny, which turns a fail-closed adapter into a 500 — and a crash is not a denial. A value
|
|
21
21
|
* that cannot be decoded is not a credential, so it reads as ABSENT, which is exactly the state every caller
|
|
22
22
|
* already handles.
|
|
23
23
|
*/
|
|
@@ -84,9 +84,88 @@ export function createAccess(config) {
|
|
|
84
84
|
return await client.can(token, scopeOf(explicit), action, intent);
|
|
85
85
|
}
|
|
86
86
|
catch {
|
|
87
|
-
return '
|
|
87
|
+
return 'unknown'; // not an answer, so not a denial either; still never `allowed`
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function whoami(req) {
|
|
91
|
+
const token = tokenOf(req);
|
|
92
|
+
if (!token)
|
|
93
|
+
return null;
|
|
94
|
+
try {
|
|
95
|
+
return await client.me(token);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function refresh(req) {
|
|
102
|
+
const refreshToken = config.refreshCookieName
|
|
103
|
+
? readCookie(req.headers.get('cookie'), config.refreshCookieName)
|
|
104
|
+
: null;
|
|
105
|
+
if (!refreshToken)
|
|
106
|
+
return { ok: false, reason: 'absent' };
|
|
107
|
+
try {
|
|
108
|
+
return { ok: true, tokens: await client.refresh(refreshToken) };
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
const rejected = e instanceof AccessError && e.status >= 400 && e.status < 500 && e.status !== 408 && e.status !== 429;
|
|
112
|
+
return { ok: false, reason: rejected ? 'rejected' : 'unavailable' };
|
|
88
113
|
}
|
|
89
114
|
}
|
|
90
|
-
|
|
115
|
+
async function logout(req) {
|
|
116
|
+
const token = tokenOf(req);
|
|
117
|
+
if (!token)
|
|
118
|
+
return 'absent';
|
|
119
|
+
try {
|
|
120
|
+
return await client.revoke(token);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return 'unknown';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { identity, scope, session, can, whoami, refresh, logout };
|
|
127
|
+
}
|
|
128
|
+
// ── Cookie binding (S2) ─────────────────────────────────────────────────────────────────────────────────────────
|
|
129
|
+
//
|
|
130
|
+
// Mechanism only: it turns a TokenSet into the Set-Cookie header VALUES a BFF route appends, with the operator plane's
|
|
131
|
+
// fixed posture (HttpOnly always: the browser never reads a token). It decides no lifetime of its own: the access
|
|
132
|
+
// cookie lives as long as the Control Plane said the access token does (`expiresIn`, or the caller's override), and
|
|
133
|
+
// the refresh cookie as long as the caller says (the Control Plane does not return the refresh token's lifetime), or
|
|
134
|
+
// for the browser's lifetime when it says nothing.
|
|
135
|
+
/** RFC 6265 cookie-name characters (a `token`). A name outside them is refused, never escaped. */
|
|
136
|
+
const COOKIE_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
137
|
+
function cookieAttrs(path, o, maxAge) {
|
|
138
|
+
if (!path.startsWith('/') || /[;\s\x00-\x1f\x7f]/.test(path))
|
|
139
|
+
throw new Error(`access: invalid cookie path ${JSON.stringify(path)}`);
|
|
140
|
+
const parts = [`Path=${path}`, 'HttpOnly', `SameSite=${o.sameSite ?? 'Lax'}`];
|
|
141
|
+
if (o.secure !== false)
|
|
142
|
+
parts.push('Secure');
|
|
143
|
+
if (maxAge !== undefined)
|
|
144
|
+
parts.push(`Max-Age=${Math.max(0, Math.floor(maxAge))}`);
|
|
145
|
+
return parts.join('; ');
|
|
146
|
+
}
|
|
147
|
+
function cookieName(name) {
|
|
148
|
+
if (!COOKIE_NAME.test(name))
|
|
149
|
+
throw new Error(`access: invalid cookie name ${JSON.stringify(name)}`);
|
|
150
|
+
return name;
|
|
151
|
+
}
|
|
152
|
+
/** The Set-Cookie values that bind `tokens` to the browser: the access cookie, then the refresh cookie when named. */
|
|
153
|
+
export function sessionCookies(tokens, o) {
|
|
154
|
+
const path = o.path ?? '/';
|
|
155
|
+
const out = [
|
|
156
|
+
`${cookieName(o.cookieName)}=${encodeURIComponent(tokens.accessToken)}; ${cookieAttrs(path, o, o.maxAgeSeconds ?? tokens.expiresIn)}`,
|
|
157
|
+
];
|
|
158
|
+
if (o.refreshCookieName) {
|
|
159
|
+
out.push(`${cookieName(o.refreshCookieName)}=${encodeURIComponent(tokens.refreshToken)}; ${cookieAttrs(o.refreshPath ?? path, o, o.refreshMaxAgeSeconds)}`);
|
|
160
|
+
}
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
/** The Set-Cookie values that clear the Operator session's cookies (Max-Age=0, same names and paths). */
|
|
164
|
+
export function clearedSessionCookies(o) {
|
|
165
|
+
const path = o.path ?? '/';
|
|
166
|
+
const out = [`${cookieName(o.cookieName)}=; ${cookieAttrs(path, o, 0)}`];
|
|
167
|
+
if (o.refreshCookieName)
|
|
168
|
+
out.push(`${cookieName(o.refreshCookieName)}=; ${cookieAttrs(o.refreshPath ?? path, o, 0)}`);
|
|
169
|
+
return out;
|
|
91
170
|
}
|
|
92
171
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -26,6 +26,61 @@ export interface OperatorIdentity {
|
|
|
26
26
|
aud: string;
|
|
27
27
|
exp?: number;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The operator as the CONTROL PLANE accepted them at the time of the call (access 0.1.3, S3). NOT the display decode:
|
|
31
|
+
* it exists only when, with the operator's own token, `GET /operator/me` answered 200 for the token's own `sub` AND
|
|
32
|
+
* the Operator session read answered `live: true` for its (`sub`, `sid`), which the Control Plane says only for an
|
|
33
|
+
* ACTIVE operator whose Operator session is not revoked or expired.
|
|
34
|
+
*
|
|
35
|
+
* What it proves: that operator, signed in, at that moment. It is not authority: what the operator may do comes only
|
|
36
|
+
* from `can()`, re-proven at the point of use. `sub` and `sid` are bound by the Control Plane's answers; `email`,
|
|
37
|
+
* `displayName` and `status` are the Control Plane's; `iss`, `aud` and `exp` are read from the token this SDK decoded
|
|
38
|
+
* (the token the Control Plane just accepted, not a second verification of those claims).
|
|
39
|
+
*/
|
|
40
|
+
export interface VerifiedOperator {
|
|
41
|
+
sub: string;
|
|
42
|
+
email: string;
|
|
43
|
+
displayName?: string;
|
|
44
|
+
/** The operator's status as the Control Plane reports it (e.g. `active`). Reported, never interpreted here. */
|
|
45
|
+
status: string;
|
|
46
|
+
/** The Operator session (sid) the token is bound to. */
|
|
47
|
+
sid: string;
|
|
48
|
+
iss: string;
|
|
49
|
+
aud: string;
|
|
50
|
+
exp?: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The outcome of revoking the Operator session (access 0.1.3, S2):
|
|
54
|
+
* - `revoked` — the Control Plane answered 2xx: the Operator session bound to the token is revoked;
|
|
55
|
+
* - `failed` — the Control Plane answered 4xx (the token was not accepted): nothing was revoked by this call;
|
|
56
|
+
* - `unknown` — a 5xx, a 408 or 429, or no answer (unreachable, a dropped response): it may or may not have landed;
|
|
57
|
+
* - `absent` — there was no token to revoke (server adapter only).
|
|
58
|
+
* Only `revoked` means "revoked"; a caller that must be sure re-tries `unknown` with the same token.
|
|
59
|
+
*/
|
|
60
|
+
export type LogoutOutcome = 'revoked' | 'failed' | 'unknown' | 'absent';
|
|
61
|
+
/**
|
|
62
|
+
* The outcome of a refresh (access 0.1.3, S2): new tokens, or why not.
|
|
63
|
+
* - `absent` — no refresh cookie;
|
|
64
|
+
* - `rejected` — the Control Plane refused the refresh token (4xx): the Operator session is over, sign in again;
|
|
65
|
+
* - `unavailable` — a 5xx, a 408 or 429, or no answer: the Operator session may still be valid, try again.
|
|
66
|
+
*/
|
|
67
|
+
export type RefreshOutcome = {
|
|
68
|
+
ok: true;
|
|
69
|
+
tokens: TokenSetShape;
|
|
70
|
+
} | {
|
|
71
|
+
ok: false;
|
|
72
|
+
reason: 'absent' | 'rejected' | 'unavailable';
|
|
73
|
+
};
|
|
74
|
+
/** The token bundle shape (mirrors `/client`'s TokenSet, declared here so the root types stay self-contained). */
|
|
75
|
+
export interface TokenSetShape {
|
|
76
|
+
accessToken: string;
|
|
77
|
+
refreshToken: string;
|
|
78
|
+
sid: string;
|
|
79
|
+
operatorId: string;
|
|
80
|
+
/** Access-token lifetime in seconds (~15m). */
|
|
81
|
+
expiresIn: number;
|
|
82
|
+
tokenType: string;
|
|
83
|
+
}
|
|
29
84
|
/**
|
|
30
85
|
* The project + environment an operator is acting in. The Control Plane keys
|
|
31
86
|
* Access decisions on the project slug; the environment travels with it (env =
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,UAAU,EAAE,MAAM,KACf,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElE;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+GAA+G;IAC/G,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExE;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAA;CAAE,CAAC;AAEjE,kHAAkH;AAClH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,MAAM,KAAK,GAAG,UAAU,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,UAAU,EAAE,MAAM,KACf,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@consciousclouds/access",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Conscious Clouds Access SDK \u2014 the thin, policy-free client for the Control Plane's operator identity + Access surface. Types (root) + isomorphic HTTP wrappers (/client) + a request-bound fail-closed BFF adapter (/server) + React hooks & AccessProvider (/react). Reuses the `Capability` `<primitive>.<verb>` vocabulary and the operator-shell's allowed|denied|unknown decision union. NO policy logic \u2014 every decision is the Control Plane's; the SDK only asks the five operating questions and enforces the answers (fail-closed).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|