first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# `principal-projection`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Projects the package's internal `UserRow` storage shape onto the abstract
`Principal` contract published by `@suaveplan/api-types`. Keeping the
projection in one place ensures that no storage-specific columns leak
into the principal seen by downstream plugins, and that the four
documented principal fields (`id`, `scopes`, `tenantId?`, `claims`) are
the only surface area authors can rely on.
The projection is deliberately strict: structurally-invalid rows raise
`AUTH_ROLLED.PRINCIPAL_PROJECTION_FAILED`, surfacing storage-driver bugs
loudly rather than letting malformed data flow into route handlers.
## Features
- One-shot pure function — no DB calls, no async, no allocations beyond
the new array of branded `Scope`s.
- Validates every column the projection touches (`id` non-empty string,
`scopes` array of non-empty strings, `claims` plain object).
- Omits `tenantId` from the output `Principal` when the storage row's
value is `null`, matching the optional shape in `Principal`.
- Brands strings as `PrincipalId` / `Scope` / `TenantId` at the boundary
so type narrowing carries through to consumers.
## Usage: Basic
```ts
import { projectUserRowToPrincipal } from "@suaveplan/api-auth-rolled";
const principal = projectUserRowToPrincipal(row);
console.log(principal.id, principal.scopes);
```
## Usage: Advanced
```ts
import { projectUserRowToPrincipal } from "@suaveplan/api-auth-rolled";
function resolveSession(row: UserRow): Principal {
try {
return projectUserRowToPrincipal(row);
} catch (err) {
// Storage adapter returned a malformed row — log + treat as an
// anonymous request rather than surfacing the bug to the client.
log.error({ err }, "principal projection failed");
throw err;
}
}
```
## API Reference
- `projectUserRowToPrincipal(row: UserRow): Principal` — pure projection.
Throws `AuthRolledError(PRINCIPAL_PROJECTION_FAILED)` on any structural
invariant violation.
## Implementation Notes
The projection allocates a fresh `scopes` array rather than spreading the
row's array — this is intentional so that downstream handlers cannot
mutate the source row through the principal reference. `claims` is a
shallow read-only reference so deep-cloning every claim object on every
request stays optional (consumers wanting deep immutability can wrap with
`Object.freeze`). The `tenantId` branding mirrors the contract published
by `@suaveplan/api-tenant-resolver-*` adapters — keeping the brand at the
projection boundary means downstream code that takes a `TenantId` never
needs an unsafe cast.