;; identity/session.sx — a session is an Erlang process.
;;
;; create  = spawn a session process holding {subject, client, status}
;; lookup  = a message; the live process answers {ok, ...} or {error, S}
;; expire  = explicit message OR an idle timeout the process arms itself
;; revoke  = explicit message; the grant tombstones immediately
;;
;; Expiry is the process's own `receive ... after Ttl` timeout, never a
;; global sweep. On timeout the process notifies its Owner and becomes a
;; tombstone that still answers lookups — with {error, expired}, never a
;; silent dead mailbox. A revoked or expired session is an explicit
;; negative state, not the absence of a positive one.

(define
  identity-session-source
  "-module(identity_session).\n\n   start(SessionId, Subject, Client, Owner, Ttl) ->\n     spawn(fun () -> active(SessionId, Subject, Client, Owner, Ttl) end).\n\n   lookup(Pid) ->\n     Pid ! {lookup, self()},\n     receive {session_reply, R} -> R end.\n\n   touch(Pid) ->\n     Pid ! {touch, self()},\n     receive {session_reply, R} -> R end.\n\n   expire(Pid) ->\n     Pid ! {expire, self()},\n     receive {session_reply, R} -> R end.\n\n   revoke(Pid) ->\n     Pid ! {revoke, self()},\n     receive {session_reply, R} -> R end.\n\n   stop(Pid) ->\n     Pid ! {stop, self()},\n     receive {session_reply, R} -> R end.\n\n   active(SessionId, Subject, Client, Owner, Ttl) ->\n     receive\n       {lookup, From} ->\n         From ! {session_reply, {ok, {SessionId, Subject, Client, active}}},\n         active(SessionId, Subject, Client, Owner, Ttl);\n       {touch, From} ->\n         From ! {session_reply, ok},\n         active(SessionId, Subject, Client, Owner, Ttl);\n       {expire, From} ->\n         From ! {session_reply, ok},\n         tombstone(SessionId, Subject, Client, expired);\n       {revoke, From} ->\n         From ! {session_reply, ok},\n         tombstone(SessionId, Subject, Client, revoked);\n       {stop, From} ->\n         From ! {session_reply, ok}\n     after Ttl ->\n       Owner ! {session_expired, SessionId},\n       tombstone(SessionId, Subject, Client, expired)\n     end.\n\n   tombstone(SessionId, Subject, Client, Status) ->\n     receive\n       {lookup, From} ->\n         From ! {session_reply, {error, Status}},\n         tombstone(SessionId, Subject, Client, Status);\n       {touch, From} ->\n         From ! {session_reply, {error, Status}},\n         tombstone(SessionId, Subject, Client, Status);\n       {expire, From} ->\n         From ! {session_reply, ok},\n         tombstone(SessionId, Subject, Client, Status);\n       {revoke, From} ->\n         From ! {session_reply, ok},\n         tombstone(SessionId, Subject, Client, revoked);\n       {stop, From} ->\n         From ! {session_reply, ok}\n     end.")

(define
  identity-load-session!
  (fn () (erlang-load-module identity-session-source)))
