// `session.me` — returns the caller's resolved identity. This is the proof the // auth loop works end-to-end, and the frontend's SSR auth gate reads it: call // it with no session cookie and you get an anonymous Subject; sign in via POST // /auth/sign-in (which sets the cookie), call it again, and // `voltroPasswordStrategy` has resolved that cookie into a `user` Subject. // Browser-safe descriptor — no server imports here. import { defineAction } from '@voltro/protocol' import { Schema } from 'effect' export const me = defineAction({ name: 'session.me', // The ONE open procedure in this app, and it has to be. The four domain // procedures beside it carry guards an anonymous caller cannot satisfy — // which is correct — but the dashboard's SSR gate has to be able to ask // "who am I" while it is still nobody, or it has nothing to branch on and the // redirect to /login never happens. // // Safe because the answer is a projection of the caller's own request: the // Subject `voltroPasswordStrategy` resolved from the cookie they sent. It // reads no table and can say nothing about anybody else. openAccess: 'echoes the caller\'s own resolved Subject (type/id/tenantId) — reads no table and reveals ' + 'nothing the caller did not present. Anonymous callers must reach it, or the SSR gate ' + 'cannot redirect them to sign in.', input: Schema.Struct({}), output: Schema.Struct({ // 'anonymous' | 'user' | 'apiKey' | 'serviceAccount' type: Schema.String, // null while anonymous; the user id once signed in. id: Schema.NullOr(Schema.String), tenantId: Schema.NullOr(Schema.String), }), })