@c1m-public/platform-auth 0.8.3 → 0.9.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 +8 -0
- package/dist/access/index.d.ts +6 -1
- package/dist/access/index.js +1 -1
- package/dist/access/next.d.ts +1 -1
- package/dist/access/next.js +2 -2
- package/dist/{chunk-73ZH67GM.js → chunk-U67NBJND.js} +7 -1
- package/dist/next.d.ts +10 -5
- package/dist/next.js +13 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,6 +116,14 @@ await access.requireAccess("platform.tenants.manage");
|
|
|
116
116
|
Omit `getSubjectId` and the loader derives the cache-tag subject from the access
|
|
117
117
|
token, so per-user tagging cannot silently collapse to one shared tag.
|
|
118
118
|
|
|
119
|
+
### Pipeline stages
|
|
120
|
+
|
|
121
|
+
`PIPELINE_STAGES` / `PipelineStage` / `isPipelineStage` under `./access` are
|
|
122
|
+
the onboarding funnel strings in order (`created`, `awaiting_payment`,
|
|
123
|
+
`provisioning`, `attention`, `active`), generated from the backend's
|
|
124
|
+
`schemas/api/pipeline-stages.json` the same way the permission keys are.
|
|
125
|
+
Labels and descriptions stay with the app; the strings are the backend's.
|
|
126
|
+
|
|
119
127
|
## Keys drift guard
|
|
120
128
|
|
|
121
129
|
`src/access/generated/keys.ts` is generated from the backend authz catalog
|
package/dist/access/index.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ type WorkspaceRole = (typeof WORKSPACE_ROLES)[number];
|
|
|
21
21
|
/** Every permission key the backend can grant, across all scopes. */
|
|
22
22
|
type PermissionKey = PlatformPermissionKey | DashPermissionKey | LeadBrokerPermissionKey | WorkspacePermissionKey;
|
|
23
23
|
|
|
24
|
+
/** Onboarding pipeline stages, in funnel order. Labels and copy stay with the app; the strings are the backend's. */
|
|
25
|
+
declare const PIPELINE_STAGES: readonly ["created", "awaiting_payment", "provisioning", "attention", "active"];
|
|
26
|
+
type PipelineStage = (typeof PIPELINE_STAGES)[number];
|
|
27
|
+
declare function isPipelineStage(value: unknown): value is PipelineStage;
|
|
28
|
+
|
|
24
29
|
type AccessErrorCode = "unauthenticated" | "forbidden" | "unavailable" | "invalid_snapshot";
|
|
25
30
|
/**
|
|
26
31
|
* Typed failure for loading or validating an access snapshot. `unauthenticated`
|
|
@@ -145,4 +150,4 @@ interface FetchAccessSnapshotOptions {
|
|
|
145
150
|
*/
|
|
146
151
|
declare function fetchAccessSnapshot(opts: FetchAccessSnapshotOptions): Promise<AccessSnapshot>;
|
|
147
152
|
|
|
148
|
-
export { type AccessEntry, type AccessErrorCode, type AccessScopeType, type AccessSnapshot, AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, type DashPermissionKey, type DashRole, type FetchAccessSnapshotOptions, LEADBROKER_PERMISSIONS, type LeadBrokerPermissionKey, PLATFORM_PERMISSIONS, type PermissionCheckOptions, type PermissionKey, type PlatformPermissionKey, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, type WorkspacePermissionKey, type WorkspaceRole, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor };
|
|
153
|
+
export { type AccessEntry, type AccessErrorCode, type AccessScopeType, type AccessSnapshot, AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, type DashPermissionKey, type DashRole, type FetchAccessSnapshotOptions, LEADBROKER_PERMISSIONS, type LeadBrokerPermissionKey, PIPELINE_STAGES, PLATFORM_PERMISSIONS, type PermissionCheckOptions, type PermissionKey, type PipelineStage, type PlatformPermissionKey, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, type WorkspacePermissionKey, type WorkspaceRole, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPipelineStage, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor };
|
package/dist/access/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from '../chunk-
|
|
1
|
+
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PIPELINE_STAGES, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPipelineStage, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from '../chunk-U67NBJND.js';
|
|
2
2
|
import '../chunk-ZWSJVE5S.js';
|
package/dist/access/next.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { R as Resolvable } from '../internal-D6RafCm2.js';
|
|
2
2
|
import { AccessSnapshot, PermissionCheckOptions } from './index.js';
|
|
3
|
-
export { AccessEntry, AccessErrorCode, AccessScopeType, AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, DashPermissionKey, DashRole, FetchAccessSnapshotOptions, LEADBROKER_PERMISSIONS, LeadBrokerPermissionKey, PLATFORM_PERMISSIONS, PermissionKey, PlatformPermissionKey, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, WorkspacePermissionKey, WorkspaceRole, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from './index.js';
|
|
3
|
+
export { AccessEntry, AccessErrorCode, AccessScopeType, AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, DashPermissionKey, DashRole, FetchAccessSnapshotOptions, LEADBROKER_PERMISSIONS, LeadBrokerPermissionKey, PIPELINE_STAGES, PLATFORM_PERMISSIONS, PermissionKey, PipelineStage, PlatformPermissionKey, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, WorkspacePermissionKey, WorkspaceRole, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPipelineStage, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from './index.js';
|
|
4
4
|
|
|
5
5
|
/** Default cache tag for one subject's snapshot: `access:<subjectId>`. */
|
|
6
6
|
declare function accessCacheTag(subjectId: string): string;
|
package/dist/access/next.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decodeTokenPayload } from '../chunk-FBC2NUH7.js';
|
|
2
|
-
import { AccessSnapshotError, fetchAccessSnapshot, isAccessSnapshotError, hasAnyPermission, hasAllPermissions, hasWorkspacePermission } from '../chunk-
|
|
3
|
-
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from '../chunk-
|
|
2
|
+
import { AccessSnapshotError, fetchAccessSnapshot, isAccessSnapshotError, hasAnyPermission, hasAllPermissions, hasWorkspacePermission } from '../chunk-U67NBJND.js';
|
|
3
|
+
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PIPELINE_STAGES, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPipelineStage, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor } from '../chunk-U67NBJND.js';
|
|
4
4
|
import { resolveValue } from '../chunk-ZWSJVE5S.js';
|
|
5
5
|
import 'server-only';
|
|
6
6
|
import { cache } from 'react';
|
|
@@ -81,6 +81,12 @@ var WORKSPACE_ROLES = [
|
|
|
81
81
|
"workspace.manager"
|
|
82
82
|
];
|
|
83
83
|
|
|
84
|
+
// src/access/generated/stages.ts
|
|
85
|
+
var PIPELINE_STAGES = ["created", "awaiting_payment", "provisioning", "attention", "active"];
|
|
86
|
+
function isPipelineStage(value) {
|
|
87
|
+
return typeof value === "string" && PIPELINE_STAGES.includes(value);
|
|
88
|
+
}
|
|
89
|
+
|
|
84
90
|
// src/access/errors.ts
|
|
85
91
|
var AccessSnapshotError = class extends Error {
|
|
86
92
|
code;
|
|
@@ -258,4 +264,4 @@ async function fetchAccessSnapshot(opts) {
|
|
|
258
264
|
return parseAccessSnapshot(body);
|
|
259
265
|
}
|
|
260
266
|
|
|
261
|
-
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor };
|
|
267
|
+
export { AccessSnapshotError, DASH_PERMISSIONS, DASH_ROLES, DEFAULT_ACCESS_ENDPOINT_PATH, LEADBROKER_PERMISSIONS, PIPELINE_STAGES, PLATFORM_PERMISSIONS, WORKSPACE_PERMISSIONS, WORKSPACE_ROLES, appScopes, dashRole, emptySnapshot, entryCoversApp, fetchAccessSnapshot, hasAllPermissions, hasAnyPermission, hasPermission, hasWorkspacePermission, isAccessSnapshotError, isPipelineStage, isPlatformOwner, managedDashes, parseAccessSnapshot, permissionsFor };
|
package/dist/next.d.ts
CHANGED
|
@@ -128,6 +128,11 @@ interface SessionStoreConfig {
|
|
|
128
128
|
/** Called when a cookie read/write fails outside a request (prerender); default swallows. */
|
|
129
129
|
onError?: (error: unknown, operation: string) => void;
|
|
130
130
|
}
|
|
131
|
+
/** Per-call overrides: a multi-host surface picks the cookie domain per request. */
|
|
132
|
+
interface SessionWriteOptions {
|
|
133
|
+
/** Ignored for `__Host-` names, which forbid Domain. */
|
|
134
|
+
cookieDomain?: string;
|
|
135
|
+
}
|
|
131
136
|
/**
|
|
132
137
|
* Session cookies for a first-party Next.js platform surface, written once.
|
|
133
138
|
*
|
|
@@ -148,24 +153,24 @@ interface SessionStoreConfig {
|
|
|
148
153
|
declare function createSessionStore(config: SessionStoreConfig): {
|
|
149
154
|
audience: string;
|
|
150
155
|
cookieNames: SessionCookieNames;
|
|
151
|
-
cookieOptions: (rememberMe: boolean, token?: string) => CookieOptions & {
|
|
156
|
+
cookieOptions: (rememberMe: boolean, token?: string, options?: SessionWriteOptions) => CookieOptions & {
|
|
152
157
|
httpOnly: true;
|
|
153
158
|
sameSite: "lax";
|
|
154
159
|
path: "/";
|
|
155
160
|
};
|
|
156
|
-
createSession: (accessToken: string, refreshToken?: string, rememberMe?: boolean) => Promise<void>;
|
|
161
|
+
createSession: (accessToken: string, refreshToken?: string, rememberMe?: boolean, options?: SessionWriteOptions) => Promise<void>;
|
|
157
162
|
writeSessionCookies: (response: Response, accessToken: string, refreshToken?: string, rememberMe?: boolean) => Response;
|
|
158
163
|
getAccessToken: () => Promise<string | null>;
|
|
159
164
|
getRefreshToken: () => Promise<string | null>;
|
|
160
165
|
getSession: () => Promise<SessionData | null>;
|
|
161
166
|
getSessionWithRefresh: () => Promise<SessionData | null>;
|
|
162
167
|
isRememberMe: () => Promise<boolean>;
|
|
163
|
-
updateAccessToken: (accessToken: string, refreshToken?: string) => Promise<void>;
|
|
164
|
-
destroySession: () => Promise<void>;
|
|
168
|
+
updateAccessToken: (accessToken: string, refreshToken?: string, options?: SessionWriteOptions) => Promise<void>;
|
|
169
|
+
destroySession: (options?: SessionWriteOptions) => Promise<void>;
|
|
165
170
|
clearSessionCookies: (response: Response) => Response;
|
|
166
171
|
requireSession: () => Promise<SessionData>;
|
|
167
172
|
isAuthenticated(): Promise<boolean>;
|
|
168
173
|
};
|
|
169
174
|
type SessionStore = ReturnType<typeof createSessionStore>;
|
|
170
175
|
|
|
171
|
-
export { CookieOptions, type PlatformFetch, type PlatformFetchConfig, type PlatformFetchTimeouts, PlatformServerFetchError, RecentAuthenticationRequiredError, SSOReauthenticationRequiredError, type SessionCookieNames, SessionData, SessionExpiredError, type SessionStore, type SessionStoreConfig, type SessionStoreRefreshConfig, authenticationErrorFor, buildForwardedRequestHeaders, controlRequest, createPlatformFetch, createSessionStore, isPlatformServerFetchError, isRecentAuthenticationRequiredError, isSSOReauthenticationRequiredError, isSessionExpiredError, mapControlError };
|
|
176
|
+
export { CookieOptions, type PlatformFetch, type PlatformFetchConfig, type PlatformFetchTimeouts, PlatformServerFetchError, RecentAuthenticationRequiredError, SSOReauthenticationRequiredError, type SessionCookieNames, SessionData, SessionExpiredError, type SessionStore, type SessionStoreConfig, type SessionStoreRefreshConfig, type SessionWriteOptions, authenticationErrorFor, buildForwardedRequestHeaders, controlRequest, createPlatformFetch, createSessionStore, isPlatformServerFetchError, isRecentAuthenticationRequiredError, isSSOReauthenticationRequiredError, isSessionExpiredError, mapControlError };
|
package/dist/next.js
CHANGED
|
@@ -176,15 +176,16 @@ function createSessionStore(config) {
|
|
|
176
176
|
timeoutMs: config.refresh.timeoutMs,
|
|
177
177
|
fetch: config.refresh.fetch
|
|
178
178
|
}) : void 0;
|
|
179
|
-
function cookieOptions(rememberMe, token) {
|
|
179
|
+
function cookieOptions(rememberMe, token, options) {
|
|
180
180
|
const maxAge = token ? tokenMaxAgeSeconds(token, maxAgeCap) : maxAgeCap;
|
|
181
|
+
const effectiveDomain = hostPrefixed ? void 0 : options?.cookieDomain ?? domain;
|
|
181
182
|
return {
|
|
182
183
|
httpOnly: true,
|
|
183
184
|
secure,
|
|
184
185
|
sameSite: "lax",
|
|
185
186
|
path: "/",
|
|
186
187
|
...rememberMe ? { maxAge } : {},
|
|
187
|
-
...
|
|
188
|
+
...effectiveDomain ? { domain: effectiveDomain } : {}
|
|
188
189
|
};
|
|
189
190
|
}
|
|
190
191
|
function assertAudience(token) {
|
|
@@ -207,13 +208,13 @@ function createSessionStore(config) {
|
|
|
207
208
|
function rememberedIn(store) {
|
|
208
209
|
return store?.get(names.rememberMe)?.value === "true";
|
|
209
210
|
}
|
|
210
|
-
async function createSession(accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true) {
|
|
211
|
+
async function createSession(accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true, options) {
|
|
211
212
|
assertAudience(accessToken);
|
|
212
213
|
const store = await jar("createSession");
|
|
213
214
|
if (!store) throw new Error("Cannot create a session outside a request");
|
|
214
|
-
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken));
|
|
215
|
-
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken));
|
|
216
|
-
store.set(names.rememberMe, rememberMe ? "true" : "false", cookieOptions(rememberMe));
|
|
215
|
+
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken, options));
|
|
216
|
+
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken, options));
|
|
217
|
+
store.set(names.rememberMe, rememberMe ? "true" : "false", cookieOptions(rememberMe, void 0, options));
|
|
217
218
|
}
|
|
218
219
|
function writeSessionCookies(response, accessToken, refreshToken, rememberMe = config.defaultRememberMe ?? true) {
|
|
219
220
|
assertAudience(accessToken);
|
|
@@ -238,13 +239,13 @@ function createSessionStore(config) {
|
|
|
238
239
|
async function isRememberMe() {
|
|
239
240
|
return rememberedIn(await jar("isRememberMe"));
|
|
240
241
|
}
|
|
241
|
-
async function updateAccessToken(accessToken, refreshToken) {
|
|
242
|
+
async function updateAccessToken(accessToken, refreshToken, options) {
|
|
242
243
|
assertAudience(accessToken);
|
|
243
244
|
const store = await jar("updateAccessToken");
|
|
244
245
|
if (!store) throw new Error("Cannot update a session outside a request");
|
|
245
246
|
const rememberMe = rememberedIn(store);
|
|
246
|
-
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken));
|
|
247
|
-
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken));
|
|
247
|
+
store.set(names.session, accessToken, cookieOptions(rememberMe, accessToken, options));
|
|
248
|
+
if (refreshToken) store.set(names.refreshToken, refreshToken, cookieOptions(rememberMe, refreshToken, options));
|
|
248
249
|
}
|
|
249
250
|
async function getSessionWithRefresh() {
|
|
250
251
|
const store = await jar("getSessionWithRefresh");
|
|
@@ -264,12 +265,12 @@ function createSessionStore(config) {
|
|
|
264
265
|
function clearOptions() {
|
|
265
266
|
return { path: "/", secure };
|
|
266
267
|
}
|
|
267
|
-
async function destroySession() {
|
|
268
|
+
async function destroySession(options) {
|
|
268
269
|
const store = await jar("destroySession");
|
|
269
270
|
if (!store) return;
|
|
270
271
|
try {
|
|
271
|
-
const
|
|
272
|
-
for (const name of [names.session, names.refreshToken, names.rememberMe]) store.delete({ name, ...
|
|
272
|
+
const attributes = cookieOptions(false, void 0, options);
|
|
273
|
+
for (const name of [names.session, names.refreshToken, names.rememberMe]) store.delete({ name, ...attributes });
|
|
273
274
|
} catch (error) {
|
|
274
275
|
onError(error, "destroySession");
|
|
275
276
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c1m-public/platform-auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Session and authorization helpers for C1M platform surfaces. The root is runtime-neutral (Web Request/Response): token/session reads, the first-party handoff (PKCE target + source), proxy session gate and coalesced refresh; ./next adds the server-only guard; ./access carries the resolved access snapshot, typed permission keys, predicates, a Next loader and React bindings",
|