@owlmeans/server-auth-session 0.1.18-rc.13 → 0.1.18-rc.15
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 -2
- package/agent-meta/manifest.json +2 -2
- package/build/consts.local.d.ts +11 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +44 -0
- package/build/consts.local.js.map +1 -0
- package/build/memory.d.ts +1 -1
- package/build/memory.d.ts.map +1 -1
- package/build/memory.js +1 -1
- package/build/memory.js.map +1 -1
- package/build/redis.d.ts +2 -2
- package/build/redis.d.ts.map +1 -1
- package/build/redis.js +1 -43
- package/build/redis.js.map +1 -1
- package/build/types.local.d.ts +4 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/package.json +6 -6
- package/src/consts.local.ts +47 -0
- package/src/memory.ts +2 -4
- package/src/redis.ts +5 -56
- package/src/types.local.ts +4 -0
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ for multi-instance production deployments.
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
bun add @owlmeans/server-auth-session@^0.1.18-rc.
|
|
10
|
+
bun add @owlmeans/server-auth-session@^0.1.18-rc.15
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
@@ -36,7 +36,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
36
36
|
your project's skill store (`.agents/skills/`):
|
|
37
37
|
|
|
38
38
|
```sh
|
|
39
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
39
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.48
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/server-auth-session",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.15",
|
|
5
|
+
"generatedAt": "2026-10-05T08:32:19.091Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AuthSessionDecision } from './types.js';
|
|
2
|
+
export declare const missing: AuthSessionDecision;
|
|
3
|
+
/**
|
|
4
|
+
* One Redis script owns each subject transition. A read-modify-save sequence lets competing
|
|
5
|
+
* grant/revoke operations overwrite a pending fence; this compares the fence id and increments
|
|
6
|
+
* the version in the same Redis command instead.
|
|
7
|
+
*/
|
|
8
|
+
export declare const transitionSubject = "\nlocal current = redis.call('GET', KEYS[1])\nlocal subject = current and cjson.decode(current) or cjson.decode(ARGV[1])\nlocal now = tonumber(ARGV[2])\nlocal expires = tonumber(ARGV[3])\nlocal state = ARGV[4]\nlocal operation = ARGV[5]\nif tonumber(subject.expiresAt) <= now then\n subject = cjson.decode(ARGV[1])\nend\nif state == 'pending' then\n subject.state = 'pending'\n subject.operationId = operation\nelse\n if subject.state == 'pending' and subject.operationId ~= operation then\n return -1\n end\n subject.state = state\n subject.operationId = cjson.null\n subject.version = tonumber(subject.version) + 1\nend\nsubject.expiresAt = math.max(tonumber(subject.expiresAt), expires)\nredis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)\nreturn tonumber(subject.version)\n";
|
|
9
|
+
/** Extend only the subject's expiry without overwriting a concurrent fence or revocation. */
|
|
10
|
+
export declare const extendSubjectExpiry = "\nlocal current = redis.call('GET', KEYS[1])\nif not current then return 0 end\nlocal subject = cjson.decode(current)\nlocal expires = tonumber(ARGV[1])\nif tonumber(subject.expiresAt) < expires then\n subject.expiresAt = expires\n redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)\nend\nreturn 1\n";
|
|
11
|
+
//# sourceMappingURL=consts.local.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.d.ts","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAErD,eAAO,MAAM,OAAO,EAAE,mBAA0C,CAAA;AAEhE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,mzBAwB7B,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,mBAAmB,4UAU/B,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const missing = { state: 'missing' };
|
|
2
|
+
/**
|
|
3
|
+
* One Redis script owns each subject transition. A read-modify-save sequence lets competing
|
|
4
|
+
* grant/revoke operations overwrite a pending fence; this compares the fence id and increments
|
|
5
|
+
* the version in the same Redis command instead.
|
|
6
|
+
*/
|
|
7
|
+
export const transitionSubject = `
|
|
8
|
+
local current = redis.call('GET', KEYS[1])
|
|
9
|
+
local subject = current and cjson.decode(current) or cjson.decode(ARGV[1])
|
|
10
|
+
local now = tonumber(ARGV[2])
|
|
11
|
+
local expires = tonumber(ARGV[3])
|
|
12
|
+
local state = ARGV[4]
|
|
13
|
+
local operation = ARGV[5]
|
|
14
|
+
if tonumber(subject.expiresAt) <= now then
|
|
15
|
+
subject = cjson.decode(ARGV[1])
|
|
16
|
+
end
|
|
17
|
+
if state == 'pending' then
|
|
18
|
+
subject.state = 'pending'
|
|
19
|
+
subject.operationId = operation
|
|
20
|
+
else
|
|
21
|
+
if subject.state == 'pending' and subject.operationId ~= operation then
|
|
22
|
+
return -1
|
|
23
|
+
end
|
|
24
|
+
subject.state = state
|
|
25
|
+
subject.operationId = cjson.null
|
|
26
|
+
subject.version = tonumber(subject.version) + 1
|
|
27
|
+
end
|
|
28
|
+
subject.expiresAt = math.max(tonumber(subject.expiresAt), expires)
|
|
29
|
+
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
30
|
+
return tonumber(subject.version)
|
|
31
|
+
`;
|
|
32
|
+
/** Extend only the subject's expiry without overwriting a concurrent fence or revocation. */
|
|
33
|
+
export const extendSubjectExpiry = `
|
|
34
|
+
local current = redis.call('GET', KEYS[1])
|
|
35
|
+
if not current then return 0 end
|
|
36
|
+
local subject = cjson.decode(current)
|
|
37
|
+
local expires = tonumber(ARGV[1])
|
|
38
|
+
if tonumber(subject.expiresAt) < expires then
|
|
39
|
+
subject.expiresAt = expires
|
|
40
|
+
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
41
|
+
end
|
|
42
|
+
return 1
|
|
43
|
+
`;
|
|
44
|
+
//# sourceMappingURL=consts.local.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consts.local.js","sourceRoot":"","sources":["../src/consts.local.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAwB,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBhC,CAAA;AAED,6FAA6F;AAC7F,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;CAUlC,CAAA"}
|
package/build/memory.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BasicContext } from '@owlmeans/context';
|
|
2
2
|
import type { AuthSessionManager, AuthSessionManagerOptions } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Process-local implementation for development and generated targets. It deliberately loses
|
package/build/memory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGpE,OAAO,KAAK,EACW,kBAAkB,EAAE,yBAAyB,EAEnE,MAAM,YAAY,CAAA;AAGnB;;;GAGG;AACH,eAAO,MAAM,4BAA4B,aAC9B,yBAAyB,KACjC,kBAiFF,CAAA;AAED,eAAO,MAAM,8BAA8B,GAAI,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,WAC/D,CAAC,YAAY,yBAAyB,KAC9C,CAIF,CAAA"}
|
package/build/memory.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createService } from '@owlmeans/context';
|
|
2
2
|
import { AUTH_SESSION_MANAGER, AUTH_SESSION_TTL } from './consts.js';
|
|
3
3
|
import { subjectId } from './identity.js';
|
|
4
|
-
|
|
4
|
+
import { missing } from './consts.local.js';
|
|
5
5
|
/**
|
|
6
6
|
* Process-local implementation for development and generated targets. It deliberately loses
|
|
7
7
|
* state on restart and is therefore never the authority for viable's centrally issued sessions.
|
package/build/memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
package/build/redis.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { type BasicContext } from '@owlmeans/context';
|
|
2
|
+
import { type RedisResource } from '@owlmeans/redis-resource';
|
|
3
3
|
import type { AuthSessionManager, AuthSessionManagerOptions } from './types.js';
|
|
4
4
|
/** Redis-backed manager. Redis `create` is SET NX, so first session registration is atomic. */
|
|
5
5
|
export declare const makeRedisAuthSessionManager: (resourceAlias?: string, options?: AuthSessionManagerOptions) => AuthSessionManager;
|
package/build/redis.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACpE,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAIhF,OAAO,KAAK,EAAE,kBAAkB,EAAE,yBAAyB,EAAoE,MAAM,YAAY,CAAA;AAIjJ,+FAA+F;AAC/F,eAAO,MAAM,2BAA2B,mBACvB,MAAM,YAAmC,yBAAyB,KAChF,kBA4GF,CAAA;AAED,eAAO,MAAM,6BAA6B,GAAI,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,WAC9D,CAAC,YAAY,yBAAyB,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KACpH,CAQF,CAAA;AAED,YAAY,EAAE,aAAa,EAAE,CAAA"}
|
package/build/redis.js
CHANGED
|
@@ -3,49 +3,7 @@ import { makeRedisResource } from '@owlmeans/redis-resource';
|
|
|
3
3
|
import { RecordExists } from '@owlmeans/resource';
|
|
4
4
|
import { AUTH_SESSION_MANAGER, AUTH_SESSION_RESOURCE, AUTH_SESSION_TTL } from './consts.js';
|
|
5
5
|
import { subjectId } from './identity.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* One Redis script owns each subject transition. A read-modify-save sequence lets competing
|
|
9
|
-
* grant/revoke operations overwrite a pending fence; this compares the fence id and increments
|
|
10
|
-
* the version in the same Redis command instead.
|
|
11
|
-
*/
|
|
12
|
-
const transitionSubject = `
|
|
13
|
-
local current = redis.call('GET', KEYS[1])
|
|
14
|
-
local subject = current and cjson.decode(current) or cjson.decode(ARGV[1])
|
|
15
|
-
local now = tonumber(ARGV[2])
|
|
16
|
-
local expires = tonumber(ARGV[3])
|
|
17
|
-
local state = ARGV[4]
|
|
18
|
-
local operation = ARGV[5]
|
|
19
|
-
if tonumber(subject.expiresAt) <= now then
|
|
20
|
-
subject = cjson.decode(ARGV[1])
|
|
21
|
-
end
|
|
22
|
-
if state == 'pending' then
|
|
23
|
-
subject.state = 'pending'
|
|
24
|
-
subject.operationId = operation
|
|
25
|
-
else
|
|
26
|
-
if subject.state == 'pending' and subject.operationId ~= operation then
|
|
27
|
-
return -1
|
|
28
|
-
end
|
|
29
|
-
subject.state = state
|
|
30
|
-
subject.operationId = cjson.null
|
|
31
|
-
subject.version = tonumber(subject.version) + 1
|
|
32
|
-
end
|
|
33
|
-
subject.expiresAt = math.max(tonumber(subject.expiresAt), expires)
|
|
34
|
-
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
35
|
-
return tonumber(subject.version)
|
|
36
|
-
`;
|
|
37
|
-
/** Extend only the subject's expiry without overwriting a concurrent fence or revocation. */
|
|
38
|
-
const extendSubjectExpiry = `
|
|
39
|
-
local current = redis.call('GET', KEYS[1])
|
|
40
|
-
if not current then return 0 end
|
|
41
|
-
local subject = cjson.decode(current)
|
|
42
|
-
local expires = tonumber(ARGV[1])
|
|
43
|
-
if tonumber(subject.expiresAt) < expires then
|
|
44
|
-
subject.expiresAt = expires
|
|
45
|
-
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
46
|
-
end
|
|
47
|
-
return 1
|
|
48
|
-
`;
|
|
6
|
+
import { extendSubjectExpiry, missing, transitionSubject } from './consts.local.js';
|
|
49
7
|
/** Redis-backed manager. Redis `create` is SET NX, so first session registration is atomic. */
|
|
50
8
|
export const makeRedisAuthSessionManager = (resourceAlias = AUTH_SESSION_RESOURCE, options = {}) => {
|
|
51
9
|
const now = options.now ?? Date.now;
|
package/build/redis.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"redis.js","sourceRoot":"","sources":["../src/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqB,MAAM,mBAAmB,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAsB,MAAM,0BAA0B,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC3F,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAEzC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGnF,+FAA+F;AAC/F,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,aAAa,GAAW,qBAAqB,EAAE,OAAO,GAA8B,EAAE,EAClE,EAAE;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAA;IACnC,MAAM,QAAQ,GAAG,CAAC,OAA0B,EAAmB,EAAE,CAC/D,OAAO,CAAC,QAAQ,CAAkB,aAAa,CAAC,CAAA;IAElD,MAAM,WAAW,GAAG,KAAK,EAAE,GAAsB,EAAE,QAA6B,EAAE,EAAU,EAA+B,EAAE;QAC3H,MAAM,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAA8B,CAAA;QACvE,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE;YAAE,OAAO,KAAK,CAAA;QACrF,MAAM,OAAO,GAAuB;YAClC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS;YACjF,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,gBAAgB;SAC9D,CAAA;QACD,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YACzE,OAAO,OAAO,CAAA;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;gBAAE,MAAM,KAAK,CAAA;YACjD,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAA8B,CAAA;YACvE,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;gBAAE,MAAM,KAAK,CAAA;YAC5D,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC,CAAA;IAED,MAAM,UAAU,GAAG,KAAK,EACtB,GAAsB,EAAE,QAA6B,EACrD,KAAuC,EAAE,WAAmB,EAC3C,EAAE;QACnB,MAAM,EAAE,GAAG,GAAG,EAAE,CAAA;QAChB,MAAM,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,IAAI,GAAuB;YAC/B,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS;YACjF,GAAG,CAAC,QAAQ,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,gBAAgB;SAC9D,CAAA;QACD,MAAM,SAAS,GAAG,EAAE,GAAG,gBAAgB,CAAA;QACvC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAC9C,iBAAiB,EAAE,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CACrG,CAAA;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACrD,CAAC;QACD,OAAO,OAAO,CAAA;IAChB,CAAC,CAAA;IAED,IAAI,OAA2B,CAAA;IAC/B,OAAO,GAAG,aAAa,CAAqB,OAAO,CAAC,KAAK,IAAI,oBAAoB,EAAE;QACjF,QAAQ,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;YACxB,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAC/B,MAAM,EAAE,GAAG,GAAG,EAAE,CAAA;YAChB,2FAA2F;YAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,GAAG,gBAAgB,EAAE,EAAE,GAAG,gBAAgB,CAAC,CAAA;YAC7F,IAAI,SAAS,IAAI,EAAE;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAChD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,CAAA;YACnD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAC5D,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAC5D,0FAA0F;YAC1F,0FAA0F;YAC1F,uDAAuD;YACvD,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;gBAClC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAChC,mBAAmB,EAAE,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,SAAS,CACjE,CAAA;YACH,CAAC;YACD,MAAM,MAAM,GAAG;gBACb,GAAG,OAAO,EAAE,MAAM,EAAE,SAAkB,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,SAAS;gBACnF,OAAO,EAAE,OAAO,CAAC,OAAO;aACzB,CAAA;YACD,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAClE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,YAAY,YAAY,CAAC;oBAAE,MAAM,KAAK,CAAA;gBACjD,oFAAoF;gBACpF,0FAA0F;gBAC1F,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;gBACpD,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;oBAAE,MAAM,KAAK,CAAA;gBAChE,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAC7G,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,CAAA;QACjE,CAAC;QACD,OAAO,EAAE,KAAK,EAAC,EAAE,EAAC,EAAE;YAClB,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAC/B,MAAM,EAAE,GAAG,GAAG,EAAE,CAAA;YAChB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YAC5C,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAA;YACnE,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YACxD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;YAC5D,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE;gBAAE,OAAO,OAAO,CAAA;YAC9F,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAC5D,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;YAC5D,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAA;QACpI,CAAC;QACD,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE;YACrC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAC/B,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAA;QACzD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE;YACvC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAC/B,OAAO,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;QAC/D,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAC/B,OAAO,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAA;QAChE,CAAC;KACF,CAAC,CAAA;IACF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,OAAU,EAAE,OAAyG,EAClH,EAAE;IACL,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,qBAAqB,CAAA;IACrE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;QACxC,OAAO,CAAC,gBAAgB,CAAC,iBAAiB,CAA0B,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAA;IAC9H,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,oBAAoB,CAAA;IACpD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,eAAe,CAAC,2BAA2B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAA;IAC5G,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.local.d.ts","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAEzD,MAAM,MAAM,eAAe,GAAG,aAAa,CAAC,uBAAuB,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.local.js","sourceRoot":"","sources":["../src/types.local.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/server-auth-session",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.15",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Short-lived OwlMeans session registry with memory and Redis implementations.",
|
|
6
6
|
"type": "module",
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
25
|
-
"@owlmeans/redis-resource": "^0.1.18-rc.
|
|
26
|
-
"@owlmeans/resource": "^0.1.18-rc.
|
|
27
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
24
|
+
"@owlmeans/context": "^0.1.18-rc.33",
|
|
25
|
+
"@owlmeans/redis-resource": "^0.1.18-rc.43",
|
|
26
|
+
"@owlmeans/resource": "^0.1.18-rc.39",
|
|
27
|
+
"@owlmeans/server-context": "^0.1.18-rc.42"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@owlmeans/dep-config": "workspace:*",
|
|
31
|
-
"@types/bun": "^1.4.
|
|
31
|
+
"@types/bun": "^1.4.2",
|
|
32
32
|
"typescript": "^7.0.2"
|
|
33
33
|
},
|
|
34
34
|
"publishConfig": {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AuthSessionDecision } from './types.js'
|
|
2
|
+
|
|
3
|
+
export const missing: AuthSessionDecision = { state: 'missing' }
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* One Redis script owns each subject transition. A read-modify-save sequence lets competing
|
|
7
|
+
* grant/revoke operations overwrite a pending fence; this compares the fence id and increments
|
|
8
|
+
* the version in the same Redis command instead.
|
|
9
|
+
*/
|
|
10
|
+
export const transitionSubject = `
|
|
11
|
+
local current = redis.call('GET', KEYS[1])
|
|
12
|
+
local subject = current and cjson.decode(current) or cjson.decode(ARGV[1])
|
|
13
|
+
local now = tonumber(ARGV[2])
|
|
14
|
+
local expires = tonumber(ARGV[3])
|
|
15
|
+
local state = ARGV[4]
|
|
16
|
+
local operation = ARGV[5]
|
|
17
|
+
if tonumber(subject.expiresAt) <= now then
|
|
18
|
+
subject = cjson.decode(ARGV[1])
|
|
19
|
+
end
|
|
20
|
+
if state == 'pending' then
|
|
21
|
+
subject.state = 'pending'
|
|
22
|
+
subject.operationId = operation
|
|
23
|
+
else
|
|
24
|
+
if subject.state == 'pending' and subject.operationId ~= operation then
|
|
25
|
+
return -1
|
|
26
|
+
end
|
|
27
|
+
subject.state = state
|
|
28
|
+
subject.operationId = cjson.null
|
|
29
|
+
subject.version = tonumber(subject.version) + 1
|
|
30
|
+
end
|
|
31
|
+
subject.expiresAt = math.max(tonumber(subject.expiresAt), expires)
|
|
32
|
+
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
33
|
+
return tonumber(subject.version)
|
|
34
|
+
`
|
|
35
|
+
|
|
36
|
+
/** Extend only the subject's expiry without overwriting a concurrent fence or revocation. */
|
|
37
|
+
export const extendSubjectExpiry = `
|
|
38
|
+
local current = redis.call('GET', KEYS[1])
|
|
39
|
+
if not current then return 0 end
|
|
40
|
+
local subject = cjson.decode(current)
|
|
41
|
+
local expires = tonumber(ARGV[1])
|
|
42
|
+
if tonumber(subject.expiresAt) < expires then
|
|
43
|
+
subject.expiresAt = expires
|
|
44
|
+
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
45
|
+
end
|
|
46
|
+
return 1
|
|
47
|
+
`
|
package/src/memory.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { createService } from '@owlmeans/context'
|
|
2
|
-
import type { BasicContext } from '@owlmeans/context'
|
|
1
|
+
import { createService, type BasicContext } from '@owlmeans/context'
|
|
3
2
|
import { AUTH_SESSION_MANAGER, AUTH_SESSION_TTL } from './consts.js'
|
|
4
3
|
import { subjectId } from './identity.js'
|
|
5
4
|
import type {
|
|
6
5
|
AuthSessionDecision, AuthSessionManager, AuthSessionManagerOptions, AuthSessionSelector,
|
|
7
6
|
AuthSessionSubject, RegisterAuthSession
|
|
8
7
|
} from './types.js'
|
|
9
|
-
|
|
10
|
-
const missing: AuthSessionDecision = { state: 'missing' }
|
|
8
|
+
import { missing } from './consts.local.js'
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* Process-local implementation for development and generated targets. It deliberately loses
|
package/src/redis.ts
CHANGED
|
@@ -1,62 +1,11 @@
|
|
|
1
|
-
import { createService } from '@owlmeans/context'
|
|
2
|
-
import type
|
|
3
|
-
import { makeRedisResource } from '@owlmeans/redis-resource'
|
|
4
|
-
import type { RedisResource } from '@owlmeans/redis-resource'
|
|
1
|
+
import { createService, type BasicContext } from '@owlmeans/context'
|
|
2
|
+
import { makeRedisResource, type RedisResource } from '@owlmeans/redis-resource'
|
|
5
3
|
import { RecordExists } from '@owlmeans/resource'
|
|
6
4
|
import { AUTH_SESSION_MANAGER, AUTH_SESSION_RESOURCE, AUTH_SESSION_TTL } from './consts.js'
|
|
7
5
|
import { subjectId } from './identity.js'
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from './types.js'
|
|
12
|
-
|
|
13
|
-
const missing: AuthSessionDecision = { state: 'missing' }
|
|
14
|
-
|
|
15
|
-
type SessionResource = RedisResource<AuthSessionStoredRecord>
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* One Redis script owns each subject transition. A read-modify-save sequence lets competing
|
|
19
|
-
* grant/revoke operations overwrite a pending fence; this compares the fence id and increments
|
|
20
|
-
* the version in the same Redis command instead.
|
|
21
|
-
*/
|
|
22
|
-
const transitionSubject = `
|
|
23
|
-
local current = redis.call('GET', KEYS[1])
|
|
24
|
-
local subject = current and cjson.decode(current) or cjson.decode(ARGV[1])
|
|
25
|
-
local now = tonumber(ARGV[2])
|
|
26
|
-
local expires = tonumber(ARGV[3])
|
|
27
|
-
local state = ARGV[4]
|
|
28
|
-
local operation = ARGV[5]
|
|
29
|
-
if tonumber(subject.expiresAt) <= now then
|
|
30
|
-
subject = cjson.decode(ARGV[1])
|
|
31
|
-
end
|
|
32
|
-
if state == 'pending' then
|
|
33
|
-
subject.state = 'pending'
|
|
34
|
-
subject.operationId = operation
|
|
35
|
-
else
|
|
36
|
-
if subject.state == 'pending' and subject.operationId ~= operation then
|
|
37
|
-
return -1
|
|
38
|
-
end
|
|
39
|
-
subject.state = state
|
|
40
|
-
subject.operationId = cjson.null
|
|
41
|
-
subject.version = tonumber(subject.version) + 1
|
|
42
|
-
end
|
|
43
|
-
subject.expiresAt = math.max(tonumber(subject.expiresAt), expires)
|
|
44
|
-
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
45
|
-
return tonumber(subject.version)
|
|
46
|
-
`
|
|
47
|
-
|
|
48
|
-
/** Extend only the subject's expiry without overwriting a concurrent fence or revocation. */
|
|
49
|
-
const extendSubjectExpiry = `
|
|
50
|
-
local current = redis.call('GET', KEYS[1])
|
|
51
|
-
if not current then return 0 end
|
|
52
|
-
local subject = cjson.decode(current)
|
|
53
|
-
local expires = tonumber(ARGV[1])
|
|
54
|
-
if tonumber(subject.expiresAt) < expires then
|
|
55
|
-
subject.expiresAt = expires
|
|
56
|
-
redis.call('SET', KEYS[1], cjson.encode(subject), 'PXAT', subject.expiresAt)
|
|
57
|
-
end
|
|
58
|
-
return 1
|
|
59
|
-
`
|
|
6
|
+
import type { AuthSessionManager, AuthSessionManagerOptions, AuthSessionSelector, AuthSessionStoredRecord, AuthSessionSubject } from './types.js'
|
|
7
|
+
import { extendSubjectExpiry, missing, transitionSubject } from './consts.local.js'
|
|
8
|
+
import type { SessionResource } from './types.local.js'
|
|
60
9
|
|
|
61
10
|
/** Redis-backed manager. Redis `create` is SET NX, so first session registration is atomic. */
|
|
62
11
|
export const makeRedisAuthSessionManager = (
|