Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
identity:start() spawns one coordinator owning the token table + session
registry and exposes the whole-domain ops. The coordinator is the owner
sessions notify on idle timeout, so an expired session deregisters itself
— timeout-driven, never swept. verify/2 answers identity only ({active,
Subject, Client, Scope}); permission is delegated to acl. 39/39.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
112 lines
4.6 KiB
Plaintext
112 lines
4.6 KiB
Plaintext
;; identity/tests/api.sx — the service facade end-to-end: login issues a
|
|
;; session + token, verify proves identity, revoke and logout take effect
|
|
;; immediately. Exercises session + token + registry through one door.
|
|
|
|
(define id-api-test-count 0)
|
|
(define id-api-test-pass 0)
|
|
(define id-api-test-fails (list))
|
|
|
|
(define
|
|
id-api-test
|
|
(fn
|
|
(name actual expected)
|
|
(set! id-api-test-count (+ id-api-test-count 1))
|
|
(if
|
|
(= actual expected)
|
|
(set! id-api-test-pass (+ id-api-test-pass 1))
|
|
(append! id-api-test-fails {:name name :expected expected :actual actual}))))
|
|
|
|
(define ida-ev erlang-eval-ast)
|
|
(define idanm (fn (v) (get v :name)))
|
|
|
|
(identity-load-all!)
|
|
|
|
;; ── login + verify (happy path) ──────────────────────────────────
|
|
|
|
(id-api-test
|
|
"login then verify is active"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, _Sid, Tok} = identity:login(Svc, alice, web, read),\n case identity:verify(Svc, Tok) of\n {active, _, _, _} -> active;\n {inactive} -> inactive\n end"))
|
|
"active")
|
|
|
|
(id-api-test
|
|
"verify returns the logged-in subject"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, _Sid, Tok} = identity:login(Svc, alice, web, read),\n case identity:verify(Svc, Tok) of\n {active, Subject, _, _} -> Subject\n end"))
|
|
"alice")
|
|
|
|
(id-api-test
|
|
"verify returns the granted scope"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, _Sid, Tok} = identity:login(Svc, bob, cli, write),\n case identity:verify(Svc, Tok) of\n {active, _, _, Scope} -> Scope\n end"))
|
|
"write")
|
|
|
|
;; ── revoke is real through the facade ────────────────────────────
|
|
|
|
(id-api-test
|
|
"revoked token verifies inactive immediately"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, _Sid, Tok} = identity:login(Svc, alice, web, read),\n identity:revoke(Svc, Tok),\n case identity:verify(Svc, Tok) of\n {active, _, _, _} -> still_valid;\n {inactive} -> inactive\n end"))
|
|
"inactive")
|
|
|
|
;; ── session lifecycle through the facade ─────────────────────────
|
|
|
|
(id-api-test
|
|
"fresh session reports active"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, Sid, _Tok} = identity:login(Svc, alice, web, read),\n identity:session_status(Svc, Sid)"))
|
|
"active")
|
|
|
|
(id-api-test
|
|
"logout makes the session gone"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, Sid, _Tok} = identity:login(Svc, alice, web, read),\n identity:logout(Svc, Sid),\n identity:session_status(Svc, Sid)"))
|
|
"gone")
|
|
|
|
(id-api-test
|
|
"status of an unknown session is gone"
|
|
(idanm
|
|
(ida-ev "Svc = identity:start(),\n identity:session_status(Svc, 999)"))
|
|
"gone")
|
|
|
|
;; ── independence: logins do not bleed into each other ────────────
|
|
|
|
(id-api-test
|
|
"revoking one login leaves the other active"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, _S1, T1} = identity:login(Svc, alice, web, read),\n {ok, _S2, T2} = identity:login(Svc, bob, cli, write),\n identity:revoke(Svc, T1),\n case identity:verify(Svc, T2) of\n {active, Subject, _, _} -> Subject;\n {inactive} -> inactive\n end"))
|
|
"bob")
|
|
|
|
(id-api-test
|
|
"logging out one session leaves the other active"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, S1, _T1} = identity:login(Svc, alice, web, read),\n {ok, S2, _T2} = identity:login(Svc, alice, cli, read),\n identity:logout(Svc, S1),\n identity:session_status(Svc, S2)"))
|
|
"active")
|
|
|
|
;; ── coordinator deregisters on a session_expired notification ────
|
|
;; A live idle session fires its own `after` timeout and notifies its
|
|
;; owner (the coordinator), which then deregisters it — timeout-driven,
|
|
;; never swept. The owner-internal path can't be observed by driving the
|
|
;; scheduler idle from the test's main process, so we assert the handler
|
|
;; directly: the mailbox is FIFO, so the expiry notification is processed
|
|
;; before the following status query.
|
|
|
|
(id-api-test
|
|
"session_expired notification deregisters the session"
|
|
(idanm
|
|
(ida-ev
|
|
"Svc = identity:start(),\n {ok, Sid, _Tok} = identity:login(Svc, alice, web, read, 50),\n active = identity:session_status(Svc, Sid),\n Svc ! {session_expired, Sid},\n identity:session_status(Svc, Sid)"))
|
|
"gone")
|
|
|
|
(define
|
|
id-api-test-summary
|
|
(str "api " id-api-test-pass "/" id-api-test-count))
|