@owlmeans/server-auth-token 0.1.18-rc.2 → 0.1.18-rc.4

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 CHANGED
@@ -6,7 +6,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
6
6
  your project's skill store (`.agents/skills/`):
7
7
 
8
8
  ```sh
9
- npx @owlmeans/agent-skills@^0.1.18-rc.14
9
+ npx @owlmeans/agent-skills@^0.1.18-rc.16
10
10
  ```
11
11
 
12
12
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/server-auth-token",
4
- "version": "0.1.18-rc.2",
5
- "generatedAt": "2026-09-10T23:12:07.519Z",
4
+ "version": "0.1.18-rc.4",
5
+ "generatedAt": "2026-09-12T12:32:46.383Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/server-auth-token
9
9
 
10
10
  **Layer:** Server
11
- **Install:** `"@owlmeans/server-auth-token": "^0.1.18-rc.2"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-auth-token": "^0.1.18-rc.4"` in `dependencies`
12
12
  **Contracts:** `@owlmeans/auth-token` — the record, the routes, the format helpers
13
13
 
14
14
  ## Key Exports
@@ -108,7 +108,7 @@ never substitutes: the primary guard stays first and still claims its own creden
108
108
  matches only a value carrying the prefix. It skips entrypoints that have no guard, and it is
109
109
  idempotent.
110
110
 
111
- **Run it after the last elevation**, because it reads the guard list each entrypoint actually ended
111
+ **Run it after the final binding**, because it reads the guard list each entrypoint actually ended
112
112
  up with.
113
113
 
114
114
  Routes that must stay behind an interactive session — opening a checkout, starting an OAuth flow,
@@ -1,3 +1,4 @@
1
+ import type { EntrypointProtocolDeclaration } from '@owlmeans/entrypoint';
1
2
  /**
2
3
  * Let an access token authenticate every route that already has a guard.
3
4
  *
@@ -10,7 +11,5 @@
10
11
  * than skipped here — a child entrypoint inherits every guard its ancestors declare and cannot
11
12
  * drop one, so the refusal has to live where the credential is inspected.
12
13
  */
13
- export declare const setupAuthTokenCoguard: (entrypoints: Array<{
14
- guards?: string[];
15
- }>, guard?: string) => void;
14
+ export declare const withAuthTokenCoguard: <Protocol extends EntrypointProtocolDeclaration>(declarations: readonly Protocol[], guard?: string) => Protocol[];
16
15
  //# sourceMappingURL=coguard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"coguard.d.ts","sourceRoot":"","sources":["../src/coguard.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,gBACnB,KAAK,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,UAAS,MAAM,KACvD,IAMF,CAAA"}
1
+ {"version":3,"file":"coguard.d.ts","sourceRoot":"","sources":["../src/coguard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,sBAAsB,CAAA;AAEzE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS,6BAA6B,gBACnE,SAAS,QAAQ,EAAE,UAAS,MAAM,KAC/C,QAAQ,EAIT,CAAA"}
package/build/coguard.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { GUARD_AUTH_TOKEN } from '@owlmeans/auth-token';
2
+ import { decorateEntrypoint } from '@owlmeans/entrypoint';
2
3
  /**
3
4
  * Let an access token authenticate every route that already has a guard.
4
5
  *
@@ -11,13 +12,9 @@ import { GUARD_AUTH_TOKEN } from '@owlmeans/auth-token';
11
12
  * than skipped here — a child entrypoint inherits every guard its ancestors declare and cannot
12
13
  * drop one, so the refusal has to live where the credential is inspected.
13
14
  */
14
- export const setupAuthTokenCoguard = (entrypoints, guard = GUARD_AUTH_TOKEN) => {
15
- entrypoints.forEach(entrypoint => {
16
- if (entrypoint.guards == null || entrypoint.guards.length < 1)
17
- return;
18
- if (entrypoint.guards.includes(guard))
19
- return;
20
- entrypoint.guards = [...entrypoint.guards, guard];
21
- });
22
- };
15
+ export const withAuthTokenCoguard = (declarations, guard = GUARD_AUTH_TOKEN) => declarations.map(declaration => {
16
+ if (declaration.guards.length < 1 || declaration.guards.includes(guard))
17
+ return declaration;
18
+ return decorateEntrypoint(declaration, { guards: [...declaration.guards, guard] });
19
+ });
23
20
  //# sourceMappingURL=coguard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"coguard.js","sourceRoot":"","sources":["../src/coguard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEvD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,WAAyC,EAAE,KAAK,GAAW,gBAAgB,EACrE,EAAE;IACR,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;QAC/B,IAAI,UAAU,CAAC,MAAM,IAAI,IAAI,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QACrE,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAM;QAC7C,UAAU,CAAC,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA"}
1
+ {"version":3,"file":"coguard.js","sourceRoot":"","sources":["../src/coguard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAGzD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,YAAiC,EAAE,KAAK,GAAW,gBAAgB,EACvD,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;IAC9C,IAAI,WAAW,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,WAAW,CAAA;IAE3F,OAAO,kBAAkB,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;AACpF,CAAC,CAAC,CAAA"}
@@ -1,4 +1,12 @@
1
- export declare const listAccessTokens: import("@owlmeans/server-entrypoint").RefedEntrypointHandler<import("@owlmeans/entrypoint").AbstractResponse<any>>;
2
- export declare const createAccessToken: import("@owlmeans/server-entrypoint").RefedEntrypointHandler<import("@owlmeans/entrypoint").AbstractResponse<any>>;
3
- export declare const revokeAccessToken: import("@owlmeans/server-entrypoint").RefedEntrypointHandler<import("@owlmeans/entrypoint").AbstractResponse<any>>;
1
+ import type { AccessTokenList, IssuedAccessToken } from '@owlmeans/auth-token';
2
+ import type { AuthTokenEntrypoints } from '@owlmeans/auth-token';
3
+ export declare const listAccessTokens: (protocol: AuthTokenEntrypoints['list']) => import("@owlmeans/server-entrypoint").BoundEntrypointHandler<import("@owlmeans/entrypoint").EntrypointProtocol<import("@owlmeans/entrypoint").OpenRequest, AccessTokenList>>;
4
+ export declare const createAccessToken: (protocol: AuthTokenEntrypoints['create']) => import("@owlmeans/server-entrypoint").BoundEntrypointHandler<import("@owlmeans/entrypoint").EntrypointProtocol<{
5
+ body: import("@owlmeans/auth-token").CreateAccessToken;
6
+ }, IssuedAccessToken>>;
7
+ export declare const revokeAccessToken: (protocol: AuthTokenEntrypoints['revoke']) => import("@owlmeans/server-entrypoint").BoundEntrypointHandler<import("@owlmeans/entrypoint").EntrypointProtocol<{
8
+ params: import("@owlmeans/auth-token").AccessTokenParams;
9
+ }, {
10
+ id: string;
11
+ }>>;
4
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAsCA,eAAO,MAAM,gBAAgB,oHAa3B,CAAA;AAEF,eAAO,MAAM,iBAAiB,oHAsC5B,CAAA;AAEF,eAAO,MAAM,iBAAiB,oHAqB5B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EAAsC,iBAAiB,EACvE,MAAM,sBAAsB,CAAA;AAM7B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AA0BhE,eAAO,MAAM,gBAAgB,aAAc,oBAAoB,CAAC,MAAM,CAAC,iLAarE,CAAA;AAEF,eAAO,MAAM,iBAAiB,aAAc,oBAAoB,CAAC,QAAQ,CAAC;;sBAsCxE,CAAA;AAEF,eAAO,MAAM,iBAAiB,aAAc,oBAAoB,CAAC,QAAQ,CAAC;;;;GAqBxE,CAAA"}
@@ -1,7 +1,7 @@
1
1
  import { AuthForbidden, AuthroizationType, ALL_SCOPES, AuthRole } from '@owlmeans/auth';
2
2
  import { AUTH_TOKEN_MAX_TTL, AUTH_TOKEN_RESOURCE } from '@owlmeans/auth-token';
3
3
  import { requireEntityKey } from '@owlmeans/auth-common';
4
- import { handleBody, handleParams, handleRequest } from '@owlmeans/server-api';
4
+ import { handlers } from '@owlmeans/server-api';
5
5
  import { mintAccessToken } from '../hash.js';
6
6
  import { prefixOf } from '../guard.js';
7
7
  const view = (record) => {
@@ -23,7 +23,7 @@ const refuseTokenAuth = (req, what) => {
23
23
  throw new AuthForbidden(what);
24
24
  }
25
25
  };
26
- export const listAccessTokens = handleRequest(async (req, context) => {
26
+ export const listAccessTokens = (protocol) => handlers().request(protocol, async (req, context) => {
27
27
  const ctx = context;
28
28
  const entityId = requireEntityKey(req);
29
29
  const profileId = req.auth?.profileId;
@@ -36,7 +36,7 @@ export const listAccessTokens = handleRequest(async (req, context) => {
36
36
  .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()),
37
37
  };
38
38
  });
39
- export const createAccessToken = handleBody(async (payload, context, req) => {
39
+ export const createAccessToken = (protocol) => handlers().body(protocol, async (payload, context, req) => {
40
40
  const ctx = context;
41
41
  refuseTokenAuth(req, 'token-mint');
42
42
  const entityId = requireEntityKey(req);
@@ -72,7 +72,7 @@ export const createAccessToken = handleBody(async (payload, context, req) => {
72
72
  // The only moment the plaintext exists outside the caller's own machine.
73
73
  return { token: minted.token, record: view(record) };
74
74
  });
75
- export const revokeAccessToken = handleParams(async (payload, context, req) => {
75
+ export const revokeAccessToken = (protocol) => handlers().params(protocol, async (payload, context, req) => {
76
76
  const ctx = context;
77
77
  refuseTokenAuth(req, 'token-revoke');
78
78
  const entityId = requireEntityKey(req);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-auth-token",
3
- "version": "0.1.18-rc.2",
3
+ "version": "0.1.18-rc.4",
4
4
  "license": "MIT",
5
5
  "description": "The server half of OwlMeans access tokens — the store, the guard that verifies a presented token, the management handlers and the coguard that admits one on an existing route.",
6
6
  "type": "module",
@@ -24,16 +24,16 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@noble/hashes": "^1.5.0",
27
- "@owlmeans/auth": "^0.1.18-rc.11",
28
- "@owlmeans/auth-common": "^0.1.18-rc.15",
29
- "@owlmeans/auth-token": "^0.1.18-rc.2",
30
- "@owlmeans/context": "^0.1.18-rc.10",
31
- "@owlmeans/entrypoint": "^0.1.18-rc.13",
32
- "@owlmeans/mongo-resource": "^0.1.18-rc.14",
33
- "@owlmeans/resource": "^0.1.18-rc.11",
34
- "@owlmeans/server-api": "^0.1.18-rc.19",
35
- "@owlmeans/server-auth-identity": "^0.1.18-rc.15",
36
- "@owlmeans/server-context": "^0.1.18-rc.14",
27
+ "@owlmeans/auth": "^0.1.18-rc.13",
28
+ "@owlmeans/auth-common": "^0.1.18-rc.17",
29
+ "@owlmeans/auth-token": "^0.1.18-rc.4",
30
+ "@owlmeans/context": "^0.1.18-rc.12",
31
+ "@owlmeans/entrypoint": "^0.1.18-rc.15",
32
+ "@owlmeans/mongo-resource": "^0.1.18-rc.16",
33
+ "@owlmeans/resource": "^0.1.18-rc.13",
34
+ "@owlmeans/server-api": "^0.1.18-rc.21",
35
+ "@owlmeans/server-auth-identity": "^0.1.18-rc.17",
36
+ "@owlmeans/server-context": "^0.1.18-rc.16",
37
37
  "@scure/base": "^1.1.9"
38
38
  },
39
39
  "devDependencies": {
package/src/coguard.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { GUARD_AUTH_TOKEN } from '@owlmeans/auth-token'
2
+ import { decorateEntrypoint } from '@owlmeans/entrypoint'
3
+ import type { EntrypointProtocolDeclaration } from '@owlmeans/entrypoint'
2
4
 
3
5
  /**
4
6
  * Let an access token authenticate every route that already has a guard.
@@ -12,12 +14,10 @@ import { GUARD_AUTH_TOKEN } from '@owlmeans/auth-token'
12
14
  * than skipped here — a child entrypoint inherits every guard its ancestors declare and cannot
13
15
  * drop one, so the refusal has to live where the credential is inspected.
14
16
  */
15
- export const setupAuthTokenCoguard = (
16
- entrypoints: Array<{ guards?: string[] }>, guard: string = GUARD_AUTH_TOKEN
17
- ): void => {
18
- entrypoints.forEach(entrypoint => {
19
- if (entrypoint.guards == null || entrypoint.guards.length < 1) return
20
- if (entrypoint.guards.includes(guard)) return
21
- entrypoint.guards = [...entrypoint.guards, guard]
22
- })
23
- }
17
+ export const withAuthTokenCoguard = <Protocol extends EntrypointProtocolDeclaration>(
18
+ declarations: readonly Protocol[], guard: string = GUARD_AUTH_TOKEN,
19
+ ): Protocol[] => declarations.map(declaration => {
20
+ if (declaration.guards.length < 1 || declaration.guards.includes(guard)) return declaration
21
+
22
+ return decorateEntrypoint(declaration, { guards: [...declaration.guards, guard] })
23
+ })
@@ -3,14 +3,14 @@ import {
3
3
  AUTH_TOKEN_MAX_TTL, AUTH_TOKEN_RESOURCE
4
4
  } from '@owlmeans/auth-token'
5
5
  import type {
6
- AccessTokenList, AccessTokenParams, AccessTokenRecord, AccessTokenView, CreateAccessToken,
7
- IssuedAccessToken
6
+ AccessTokenList, AccessTokenRecord, AccessTokenView, IssuedAccessToken
8
7
  } from '@owlmeans/auth-token'
9
8
  import { requireEntityKey } from '@owlmeans/auth-common'
10
- import { handleBody, handleParams, handleRequest } from '@owlmeans/server-api'
9
+ import { handlers } from '@owlmeans/server-api'
11
10
  import { mintAccessToken } from '../hash.js'
12
11
  import { prefixOf } from '../guard.js'
13
12
  import type { AccessTokenResource, AuthTokenContext } from '../types.js'
13
+ import type { AuthTokenEntrypoints } from '@owlmeans/auth-token'
14
14
 
15
15
  const view = (record: AccessTokenRecord): AccessTokenView => {
16
16
  const { hash, ...rest } = record
@@ -36,7 +36,7 @@ const refuseTokenAuth = (req: { auth?: { type?: string } }, what: string): void
36
36
  }
37
37
  }
38
38
 
39
- export const listAccessTokens = handleRequest(async (req, context) => {
39
+ export const listAccessTokens = (protocol: AuthTokenEntrypoints['list']) => handlers<AuthTokenContext>().request(protocol, async (req, context) => {
40
40
  const ctx = context as AuthTokenContext
41
41
  const entityId = requireEntityKey(req)
42
42
  const profileId = req.auth?.profileId
@@ -51,7 +51,7 @@ export const listAccessTokens = handleRequest(async (req, context) => {
51
51
  } satisfies AccessTokenList
52
52
  })
53
53
 
54
- export const createAccessToken = handleBody<CreateAccessToken>(async (payload, context, req) => {
54
+ export const createAccessToken = (protocol: AuthTokenEntrypoints['create']) => handlers<AuthTokenContext>().body(protocol, async (payload, context, req) => {
55
55
  const ctx = context as AuthTokenContext
56
56
  refuseTokenAuth(req, 'token-mint')
57
57
 
@@ -91,7 +91,7 @@ export const createAccessToken = handleBody<CreateAccessToken>(async (payload, c
91
91
  return { token: minted.token, record: view(record) } satisfies IssuedAccessToken
92
92
  })
93
93
 
94
- export const revokeAccessToken = handleParams<AccessTokenParams>(async (payload, context, req) => {
94
+ export const revokeAccessToken = (protocol: AuthTokenEntrypoints['revoke']) => handlers<AuthTokenContext>().params(protocol, async (payload, context, req) => {
95
95
  const ctx = context as AuthTokenContext
96
96
  refuseTokenAuth(req, 'token-revoke')
97
97
 
@@ -1,36 +1,34 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
2
  import { GUARD_AUTH_TOKEN } from '@owlmeans/auth-token'
3
- import { setupAuthTokenCoguard } from '../src/coguard.js'
3
+ import { openProtocol } from '@owlmeans/entrypoint'
4
+ import { route } from '@owlmeans/route'
5
+ import { withAuthTokenCoguard } from '../src/coguard.js'
4
6
 
5
7
  describe('@owlmeans/server-auth-token — the coguard', () => {
6
- test('appends to a guarded entrypoint and leaves the primary guard first', () => {
7
- const entrypoints = [{ guards: ['auth'] }]
8
- setupAuthTokenCoguard(entrypoints)
8
+ test('decorates a guarded protocol and leaves the primary guard first', () => {
9
+ const guarded = openProtocol(route('guarded', '/guarded'), { guards: 'auth' })
10
+ const [decorated] = withAuthTokenCoguard([guarded])
9
11
 
10
- expect(entrypoints[0].guards).toEqual(['auth', GUARD_AUTH_TOKEN])
12
+ expect(decorated.guards).toEqual(['auth', GUARD_AUTH_TOKEN])
13
+ expect(guarded.guards).toEqual(['auth'])
11
14
  })
12
15
 
13
- test('leaves an unguarded entrypoint unguarded', () => {
14
- // A public route stays public: adding a guard here would turn an open page into a 401.
15
- const entrypoints: Array<{ guards?: string[] }> = [{}, { guards: [] }]
16
- setupAuthTokenCoguard(entrypoints)
17
-
18
- expect(entrypoints[0].guards).toBeUndefined()
19
- expect(entrypoints[1].guards).toEqual([])
16
+ test('leaves an unguarded protocol unchanged', () => {
17
+ const open = openProtocol(route('open', '/open'))
18
+ expect(withAuthTokenCoguard([open])[0]).toBe(open)
20
19
  })
21
20
 
22
- test('is idempotent — a second pass adds nothing', () => {
23
- const entrypoints = [{ guards: ['auth'] }]
24
- setupAuthTokenCoguard(entrypoints)
25
- setupAuthTokenCoguard(entrypoints)
21
+ test('is idempotent', () => {
22
+ const guarded = openProtocol(route('guarded', '/guarded'), { guards: 'auth' })
23
+ const [once] = withAuthTokenCoguard([guarded])
24
+ const [twice] = withAuthTokenCoguard([once])
26
25
 
27
- expect(entrypoints[0].guards).toEqual(['auth', GUARD_AUTH_TOKEN])
26
+ expect(twice.guards).toEqual(['auth', GUARD_AUTH_TOKEN])
28
27
  })
29
28
 
30
29
  test('honours a custom guard alias', () => {
31
- const entrypoints = [{ guards: ['auth'] }]
32
- setupAuthTokenCoguard(entrypoints, 'other-guard')
33
-
34
- expect(entrypoints[0].guards).toEqual(['auth', 'other-guard'])
30
+ const guarded = openProtocol(route('guarded', '/guarded'), { guards: 'auth' })
31
+ expect(withAuthTokenCoguard([guarded], 'other-guard')[0].guards)
32
+ .toEqual(['auth', 'other-guard'])
35
33
  })
36
34
  })
@@ -1,24 +1,32 @@
1
1
  import { describe, expect, test } from 'bun:test'
2
2
  import { AuthroizationType, AuthRole } from '@owlmeans/auth'
3
- import { AUTH_TOKEN_RESOURCE } from '@owlmeans/auth-token'
3
+ import { AUTH_TOKEN_RESOURCE, makeAuthTokenEntrypoints } from '@owlmeans/auth-token'
4
4
  import type { AccessTokenRecord, IssuedAccessToken } from '@owlmeans/auth-token'
5
- import { createAccessToken, listAccessTokens, revokeAccessToken } from '../src/handlers/index.js'
5
+ import {
6
+ createAccessToken as bindCreateAccessToken,
7
+ listAccessTokens as bindListAccessTokens,
8
+ revokeAccessToken as bindRevokeAccessToken,
9
+ } from '../src/handlers/index.js'
6
10
  import { hashAccessToken } from '../src/hash.js'
7
11
  import { makeTestContext, seedProfile, seedToken, TEST_ENTITY, TEST_PREFIX, TEST_PROFILE, TEST_USER } from './context.js'
8
12
 
9
13
  /**
10
- * A handler is a `RefedEntrypointHandler`: it is given the entrypoint reference it was elevated
11
- * onto and answers with `(req, res)`. Calling it directly is what lets these tests be about the
12
- * RULES — who may mint, what a list shows, whose token may be revoked — rather than about routing.
14
+ * A protocol-bound implementation is run with the smallest binding context the transport needs.
15
+ * This keeps the tests about the authorization rules rather than a router's alias lookup.
13
16
  */
14
17
  const invoke = async (handler: any, context: any, req: any): Promise<any> => {
15
18
  const res: any = { resolve: (value: unknown) => { res.value = value }, reject: (e: Error) => { res.error = e } }
16
- await handler({ ref: { ctx: context } })(req, res)
19
+ await handler.bind({ ref: { ctx: context } })(req, res)
17
20
  if (res.error != null) throw res.error
18
21
 
19
22
  return res.value
20
23
  }
21
24
 
25
+ const protocols = makeAuthTokenEntrypoints()
26
+ const listAccessTokens = bindListAccessTokens(protocols.list)
27
+ const createAccessToken = bindCreateAccessToken(protocols.create)
28
+ const revokeAccessToken = bindRevokeAccessToken(protocols.revoke)
29
+
22
30
  const session = (patch: Record<string, unknown> = {}): any => ({
23
31
  headers: {}, params: {}, query: {}, body: {},
24
32
  entity: { id: TEST_ENTITY, slug: TEST_ENTITY },