Changelog

Releases

Two distributions, one behaviour: univeros/polaris, the Univeros module, and the polaris/* packages it is built on.

Polaris for Univeros

Rendered from univeros/polaris at v2.0.0 · View source

All notable changes to univeros/polaris are documented in this file. The format follows Keep a Changelog, and the project adheres to Semantic Versioning.

2.0.0 - 2026-09-11

univeros/polaris 2.0 is a new major built on Polaris for PHP: polaris/core carries the identity, MFA/OTP, session, organization and RBAC services, the 52 endpoints and the schema, all contract-frozen against 1.0 (184 recorded request/response sequences replay through this module’s Relay pipeline in CI); this package is the Univeros module around it. The HTTP contract of 1.0 is unchanged (docs/auth/api-reference.md in polaris-core), with one documented exception: a request body field named like a request attribute no longer overrides the attribute.

Changed

  • The module builds Polaris from the environment (APP_KEY, AUTH_JWT_*, AUTH_ISSUER, AUTH_AUDIENCE) on the application’s database settings (DB_*, or POLARIS_DSN without an ORM) through polaris/pdo; the framework’s cache, logger and event dispatcher are used when bound.
  • Routes: PolarisMiddleware, contributed through MiddlewareProviderInterface ahead of the framework’s exception handler, serves every Polaris path; the routes are no longer in the FastRoute table (bin/altair polaris:manifest lists them). POLARIS_PATH_PREFIX mounts them under a prefix.
  • Migrations: one Cycle migration installs the schema and seeds the permission catalog through Polaris\Pdo\SchemaInstaller; the 18 migrations of 1.x are gone. bin/altair db:migrate on a fresh database installs Polaris.
  • The framework’s TokenAuthenticationMiddleware keeps working with Polaris access tokens through TokenFactoryBridge; the application scopes it to its protected paths with $container->make(TokenAuthenticationMiddleware::class, ['rules' => [...]]).
  • Console: polaris:schema:export, polaris:schema:create, polaris:schema:drop, polaris:schema:diff, polaris:manifest, polaris:doctor from polaris/cli, added by the application’s own bin/altair through Univeros\Polaris\Console\Commands::all().
  • The default token issuer without AUTH_ISSUER is polaris (1.x minted univeros/polaris).

Removed

  • Every class under Univeros\Polaris\ except the module glue; use the Polaris\ namespaces of polaris/core. Cycle entities and repositories: Polaris no longer maps entities into the application’s ORM schema.
  • The AES-CBC encrypter of 1.x. There is no compatibility path (see UPGRADE).

1.0.0 - 2026-06-11

First stable release: the authentication, MFA/OTP, and multi-tenant RBAC module for the univeros framework. A host registers one Module class and gets the full surface below as routes, entities, migrations, middleware, and PSR-14 events. See docs/auth/ for the specification and docs/auth/api-reference.md for the implemented HTTP contracts (52 endpoints).

Identity and sessions

  • Registration with email verification (single-use hashed tokens, enumeration-safe responses) and resend.
  • Password login with Argon2id hashing, transparent rehash, timing-equalized verification, sliding-window lockout, and optional verified-email and HIBP breach-check (k-anonymity) gates.
  • JWT access tokens (RSA, JWKS endpoint, key-rotation overlap window) plus opaque rotating refresh tokens with family-based reuse detection: replaying a rotated token revokes the whole session family.
  • Session management: device list, logout, logout-all, per-session revocation, and an optional instant access-token denylist.
  • Password forgot/reset/change with logout-everywhere semantics; reset and verification tokens are stored only as keyed HMACs.

MFA

  • TOTP (RFC 6238, encrypted secrets, QR provisioning), SMS, and email factors with enrollment + confirmation flows; ten single-use recovery codes issued on the first confirmed factor.
  • The login MFA gate: a short-lived single-purpose ticket bridges the password step to factor verification before any session is minted.
  • Step-up re-authentication for sensitive operations, stamped via auth_time; mfa/amr/auth_time persist across refresh and org switching.
  • OTP hygiene: codes stored as keyed HMACs, attempt budgets and consumption enforced by atomic conditional updates, send quotas and resend cooldowns against OTP bombing.

Multi-tenant RBAC

  • Organizations with soft delete, slug uniqueness, and per-org role templates (owner / admin / member) cloned from system templates; a global superadmin override for platform operators.
  • Members: listing (with PII gating of invited/suspended emails), role assignment, suspension with immediate org-scoped session revocation, and removal.
  • Single-use, expiring invitations bound to the invitee’s email.
  • Custom roles with a 12-key permission catalog; database-resolved authorization on every check (token claims are never trusted for authority).
  • Tenant invariants enforced beyond the permission check: no privilege escalation, owners protected from non-owners, last-owner protection, cross-tenant isolation on every org route.
  • User administration: read/update (self or admin), disable/enable, and anonymizing tombstone deletion.

Hardening and operations

  • Per-IP rate-limit budgets per endpoint group plus a global per-user budget across authenticated endpoints; user-agent sanitization at the edge.
  • Two security audits (#44 sign-off and the #97 follow-ups) fully remediated: atomic rotation/OTP/recovery claims, APP_KEY minimum length, full-length key fingerprints, typed challenge purposes, abuse caps.
  • Append-only audit log (actor, org, ip, user agent, whitelisted metadata), domain metrics counter, and notification listeners over a catalog of ~35 PSR-14 events.
  • 18 driver-portable migrations, scheduled pruning of expired transient rows, and a key-rotation runbook.
  • Verified by 519 tests (unit, persistence against a real driver, and end-to-end functional tests over the real middleware pipeline), with phpcs (PSR-12) and phpstan level 5 clean.

Documentation and agent experience

  • Full specification under docs/auth/ with the API reference and event catalog regenerated from the shipped code.
  • One YAML spec per implemented endpoint under api/, verified 1:1 against the route table.
  • An agent skill at .ai/skills/polaris/SKILL.md covering registration, configuration, the token model, the permission catalog, and the tenant invariants.

Polaris for PHP

Rendered from univeros/polaris-core at v0.1.0 · View source

All notable changes to Polaris for PHP (the polaris/* packages) are documented in this file. The format follows Keep a Changelog, and the project adheres to Semantic Versioning.

Unreleased

0.1.0 - 2026-09-10

The first release of Polaris for PHP: the framework-agnostic packages extracted from univeros/polaris 1.0.0 with every response contract-frozen, the Laravel, Symfony and Yii adapters, and the TypeScript client. One version line for all of them.

Framework adapters

  • polaris/laravel (Polaris\Laravel\): a service provider that builds Polaris from config/polaris.php on Laravel’s connection, cache, logger, events and mailer; the 52 endpoints as named Laravel routes under path_prefix; the polaris guard (auth:polaris) for the application’s own routes; polaris:install (config and the migration that creates the tables and seeds the catalog) and the CLI commands as polaris:schema:export, polaris:schema:diff, polaris:manifest, polaris:doctor; a plain-text mail bridge (mailer: mail). The functional suite and the 184 contract fixtures replay through Laravel’s HTTP kernel in CI; examples/laravel runs the shared walkthrough. Spec and decisions in docs/adapters/.
  • polaris/symfony (Polaris\Symfony\): a bundle whose polaris: configuration becomes the Polaris, Graph and Pipeline services on the application’s connection (a DSN, a PDO, a Doctrine DBAL connection), cache, logger, dispatcher and mailer; the polaris route loader mounts the 52 endpoints as named routes; the authenticator (custom_authenticators) guards the application’s firewalls with Polaris access tokens; polaris:schema:create, polaris:schema:drop and the CLI commands as polaris:*; a plain-text Symfony Mailer bridge (mailer: mail). The functional suite and the 184 contract fixtures replay through Symfony’s HTTP kernel in CI; examples/symfony runs the shared walkthrough.
  • polaris/yii (Polaris\Yii\): a yiisoft/config plugin whose polaris params become the Config, Polaris, Graph and Pipeline definitions on the application’s connection (a DSN, a PDO or a Yiisoft\Db connection), cache, logger, dispatcher and mailer; the 52 endpoints as routes in the routes group, PSR-15 straight through; an authentication method and the polaris/authentication middleware for the application’s own routes; the polaris:* commands for yiisoft/yii-console; a plain-text Yii mailer bridge (mailer: mail). The functional suite and the 184 contract fixtures replay through the Yii application in CI; examples/yii runs the shared walkthrough.
  • polaris/pdo: SchemaInstaller creates the tables and seeds the catalog on a connection, or drops them; the adapters’ migrations and commands call it.
  • polaris/cli: schema:create and schema:drop (--dsn, or a host’s connection).
  • polaris/core: Polaris\Notification\MailTemplates, the plain-text subjects and bodies the Symfony and Yii mail bridges send.
  • polaris/cli: schema:diff and doctor accept a host’s connection, secrets and auth settings; symfony/* constraints allow Symfony 8.

TypeScript client

  • @polaris-auth/client (packages/client-ts, npm): createClient({ baseUrl, token }) over openapi-fetch, typed by src/schema.d.ts, which openapi-typescript generates from polaris manifest --format=openapi; withToken() binds another token. Checked in and drift-checked in CI; the smoke test runs register, verify, login and /auth/me through the client against the Slim demo.
  • polaris manifest --format=openapi types every success response from the spec’s output.example (Polaris\Http\Manifest\ExampleSchema, JSON Schema by example; example_<variant> keys become a oneOf), so the generated client types data.

Polaris for PHP: the framework-agnostic extraction

The 1.0 Univeros module became a monorepo of framework-free packages with the same behaviour: polaris/core (Polaris\), polaris/psr15, polaris/pdo, polaris/testing, polaris/cli. Every 1.0 response is contract-frozen: the functional suite replays 184 request/response sequences (1,201 steps) recorded from the 1.0 code through the PSR-15 pipeline. The extraction is documented in docs/extraction/ (spec, decisions, the one behaviour change).

  • Wiring. Polaris::create(new Polaris\Wiring\Config(...)) builds the service graph without a container; Polaris\Psr15\Pipeline gives any PSR-15 host the ordered middleware and the request handler.
  • Persistence. Models are plain records; the schema is data (Polaris\Schema); repositories run on a DatabaseAdapter (polaris/pdo for PostgreSQL, MySQL and SQLite; an in-memory adapter in polaris/testing). The 18 Cycle migrations are replaced by polaris schema:export.
  • Routing. packages/core/api/**/*.yaml, shipped inside polaris/core, is the router: 52 endpoints, each with effect and receipt, loaded by Polaris\Http\Manifest; the CLI renders OpenAPI 3.1.
  • Ports. Repository, unit of work, tokens, identity provider, encrypter (SodiumEncrypter default, XChaCha20-Poly1305), rate store (PSR-16 default), metrics (PSR-3 default); PSR-14 listeners exposed through Polaris::listeners().
  • CLI. bin/polaris schema:export, schema:diff, manifest, doctor.
  • Demo. examples/slim: Slim 4 on SQLite with an executable walkthrough.
  • Behaviour change (documented). A request body field named like a request attribute no longer overrides the attribute (docs/extraction/behaviour-changes.md).

1.0.0 - 2026-06-11

First stable release: the authentication, MFA/OTP, and multi-tenant RBAC module for the univeros framework. A host registers one Module class and gets the full surface below as routes, entities, migrations, middleware, and PSR-14 events. See docs/auth/ for the specification and docs/auth/api-reference.md for the implemented HTTP contracts (52 endpoints).

Identity and sessions

  • Registration with email verification (single-use hashed tokens, enumeration-safe responses) and resend.
  • Password login with Argon2id hashing, transparent rehash, timing-equalized verification, sliding-window lockout, and optional verified-email and HIBP breach-check (k-anonymity) gates.
  • JWT access tokens (RSA, JWKS endpoint, key-rotation overlap window) plus opaque rotating refresh tokens with family-based reuse detection: replaying a rotated token revokes the whole session family.
  • Session management: device list, logout, logout-all, per-session revocation, and an optional instant access-token denylist.
  • Password forgot/reset/change with logout-everywhere semantics; reset and verification tokens are stored only as keyed HMACs.

MFA

  • TOTP (RFC 6238, encrypted secrets, QR provisioning), SMS, and email factors with enrollment + confirmation flows; ten single-use recovery codes issued on the first confirmed factor.
  • The login MFA gate: a short-lived single-purpose ticket bridges the password step to factor verification before any session is minted.
  • Step-up re-authentication for sensitive operations, stamped via auth_time; mfa/amr/auth_time persist across refresh and org switching.
  • OTP hygiene: codes stored as keyed HMACs, attempt budgets and consumption enforced by atomic conditional updates, send quotas and resend cooldowns against OTP bombing.

Multi-tenant RBAC

  • Organizations with soft delete, slug uniqueness, and per-org role templates (owner / admin / member) cloned from system templates; a global superadmin override for platform operators.
  • Members: listing (with PII gating of invited/suspended emails), role assignment, suspension with immediate org-scoped session revocation, and removal.
  • Single-use, expiring invitations bound to the invitee’s email.
  • Custom roles with a 12-key permission catalog; database-resolved authorization on every check (token claims are never trusted for authority).
  • Tenant invariants enforced beyond the permission check: no privilege escalation, owners protected from non-owners, last-owner protection, cross-tenant isolation on every org route.
  • User administration: read/update (self or admin), disable/enable, and anonymizing tombstone deletion.

Hardening and operations

  • Per-IP rate-limit budgets per endpoint group plus a global per-user budget across authenticated endpoints; user-agent sanitization at the edge.
  • Two security audits (#44 sign-off and the #97 follow-ups) fully remediated: atomic rotation/OTP/recovery claims, APP_KEY minimum length, full-length key fingerprints, typed challenge purposes, abuse caps.
  • Append-only audit log (actor, org, ip, user agent, whitelisted metadata), domain metrics counter, and notification listeners over a catalog of ~35 PSR-14 events.
  • 18 driver-portable migrations, scheduled pruning of expired transient rows, and a key-rotation runbook.
  • Verified by 519 tests (unit, persistence against a real driver, and end-to-end functional tests over the real middleware pipeline), with phpcs (PSR-12) and phpstan level 5 clean.

Documentation and agent experience

  • Full specification under docs/auth/ with the API reference and event catalog regenerated from the shipped code.
  • One YAML spec per implemented endpoint under api/, verified 1:1 against the route table.
  • An agent skill at .ai/skills/polaris/SKILL.md covering registration, configuration, the token model, the permission catalog, and the tenant invariants.