Meet Polaris: A Complete PHP Identity Stack in One Line of Config (Part 1) A developer has built Polaris, an official identity module for the Univeros PHP framework, which provides a complete authentication stack with just one line of configuration. The module automatically registers 52 endpoints, including auth, users, and orgs routes, along with Cycle ORM entities, migrations, and middleware, eliminating the need for per-module bootstrapping. The developer emphasizes that the module's design prevents common auth code issues by decoupling it from the host application. This blog post series picks up where I left off in how AI agents revived my old PHP framework project. In my previous post, I wrote about how a swarm of AI agents helped me revive a PHP framework I had abandoned years ago. That post was the origin story. This little series is the first real proof that the revival was worth it. Because a framework on its own is just plumbing. What I really wanted to know was simpler and scarier: could I build a serious, production-grade feature on top of it without hating my life? Not another to-do list demo. The thing every app needs, nobody enjoys writing, and that ruins your week when you get it wrong. Authentication. So I built Polaris https://polaris.univeros.io/ . It is the official identity module for Univeros https://univeros.io/ , and this post is the tour. The four how-tos that follow get hands-on with each piece. Here I just want to show you the shape of the thing and why it is built the way it is. I named it Polaris on purpose. Polaris is the fixed star sailors navigated by, and identity plays the same role in an application. Everything else eventually comes back to "Who is this, and what are they allowed to do?" Install it: composer require univeros/polaris Register it. This is the "one line" I keep bragging about: // config/modules.php return new Univeros\Polaris\Module , ; Give it the secrets it needs from your environment or a secret manager, never from a file in the repo : export APP KEY="…" 32-byte base64, seeds the peppers + encrypter export AUTH JWT PRIVATE KEY="$ cat private.pem " signs access tokens export AUTH JWT PUBLIC KEY="$ cat public.pem " verification + the JWKS endpoint Run the migrations and confirm it is alive: bin/altair db:migrate bin/altair routes:list --format=json | grep auth bin/altair doctor That is it. That single new Module contributes every /auth , /users , and /orgs route, the Cycle ORM entities, the migrations, the authentication and authorization middleware, and the container bindings. Fifty-two endpoints, wired and ready, with zero per-module bootstrapping on your side. Here is something I learned the hard way over the years. Most auth code doesn’t die because the crypto is wrong, but because it is welded to the app that hosts it. You write a beautiful login flow for project A, then project B comes along and you spend two days surgically extracting it. By the time you’re done you’ve introduced three new bugs. Univeros has a module contract system, and Polaris leans on it completely. A module declares what it provides routes, entities, migrations, middleware, container bindings and the host wires it all in automatically. There is no "now go register these fifteen services" step: final class Module implements ModuleInterface, RoutesProviderInterface, MiddlewareProviderInterface, EntityDirectoriesProviderInterface, MigrationDirectoriesProviderInterface { public function name : string { return 'univeros/polaris'; } public function apply Container $container : void { $authConfig = AuthConfig::fromArray $this- authConfigArray ; $secrets = Secrets::fromEnvironment $this- environment ; $container- instance AuthConfig::class, $authConfig ; $container- instance Secrets::class, $secrets ; new IdentityBindings - apply $container ; new TokenBindings - apply $container, $authConfig, $secrets ; new SessionBindings - apply $container ; new HttpBindings - apply $container ; new MfaBindings - apply $container, $authConfig, $secrets ; new OrganizationBindings - apply $container ; } } Notice that apply builds the config and secrets eagerly. That is deliberate. Forget to set AUTH JWT PRIVATE KEY , and the app does not boot with a quietly insecure fallback and bite you in production three weeks later. It fails immediately, with a clear message. Fail loud. Fail early. Before diving into the how-tos, there’s one pattern worth knowing. Once you see it, the rest of the module reads the same way. Univeros uses an Action, Input, Domain, Responder shape it is basically Action-Domain-Responder with a typed input DTO in front . Every endpoint is the same quad: HTTP edge Action thin route target: declares input, responder, domain, required permissions Input readonly a typed request DTO with validation rules Responder turns a Payload into JSON or an RFC 9457 Problem Details body Domain Service the business logic: transactional, emits PSR-14 events Contracts/ ports: SmsSender, OtpMailer, PasswordHasher, Clock, and friends Persistence Entity/ Cycle UUID-v7 entities mapped into the host ORM schema Security token machinery implements the framework's Altair\Http auth contracts The domains stay thin. They validate the edge, call a service, and translate outcomes into HTTP. All the real work hashing, lockout, token minting, event dispatch lives in the services. That separation keeps the codebase from rotting, and it is why each how-to in this series can show you a real, unedited domain class that still fits on a single screen. Authentication: Register, email verification, password login, /auth/me, logout / logout-all Part 2, coming soon Tokens: Asymmetric JWT access tokens RS256/EdDSA plus opaque rotating refresh tokens with reuse detection; a JWKS endpoint Part 2, coming soon Sessions: Per-device session list, individual and global revocation Part 2, coming soon MFA / OTP: TOTP QR , SMS OTP, email OTP, recovery codes, the login-MFA gate, step-up Part 3, coming soon Passwords: Argon2id, policy enforcement, breached-password hook, reset and change Part 2, coming soon Multi-tenant RBAC: Organizations, memberships, roles, permissions, invitations, org switching Part 4, coming soon Authorization: Declarative permission guard middleware plus a programmatic Gate Part 4, coming soon Providers & events: Pluggable SMS/email/breach ports, PSR-14 domain events Part 5, coming soon I am not going to wave my hands and say "secure by design." Here is what that phrase actually cashes out to: Passwords hashed with Argon2id, transparently rehashed when parameters change, with timing-equalized verification. Access tokens signed with asymmetric keys RS256 or EdDSA with kid-based rotation. Resource servers verify with the public key alone. Refresh tokens, OTP codes, recovery codes, verification tokens, and reset tokens are never stored in plaintext. They are hashed or kept as keyed HMACs. Rotating refresh tokens with family-based reuse detection. Rate limiting on every sensitive endpoint, sliding-window account lockout, and anti-enumeration on register, resend, and forgot-password. An audit log fed by the event stream. The standards it follows are the boring, correct ones: JWT RFC 7519 , JWKS RFC 7517 , TOTP RFC 6238 , OAuth 2.0 refresh semantics and the Security BCP RFC 9700 , Problem Details RFC 9457 , and OWASP ASVS for password storage. The full threat model lives in the reference docs https://polaris.univeros.io/docs/ . That was the whole point of this exercise. Part one of the Univeros series asked whether AI agents could resurrect a dead PHP framework. This series is the honest test: could I build something genuinely hard on top of it? I think the answer is yes, and the evidence is in the shape of the code. Polaris is fifty-two endpoints, full MFA, multi-tenant RBAC, rotating tokens with theft detection, and an audit trail, and yet every endpoint is the same readable quad. The framework's module system meant the whole thing installs in one line. The agents helped a lot with the grind: the RFC 6238 test vectors, functional tests for fifty-two endpoints, keeping the docs in sync with code. But the design decisions authority comes from the database, not the token; last-owner protection; fail-open breach checks came from years of getting auth wrong and remembering the scars. The agents are fast hands. The judgment is still mine. Pick the piece you need: Part 2: Logins that do not leak covers register, email verification, password login, JWT access tokens, and rotating refresh tokens with reuse detection. coming soon Part 3: Real MFA in an afternoon covers TOTP/QR, SMS, email, recovery codes, the login gate, and step-up. coming soon Part 4: One user, many orgs covers organizations, roles, permissions, the Gate, and the tenant invariants. coming soon Part 5: Bring your own providers and events covers the SMS/email/breach ports and the PSR-14 event stream. coming soon The reference docs live at polaris.univeros.io. The framework is at univeros.io. The source is on GitHub https://github.com/univeros/polaris . composer require univeros/polaris One line. A whole identity stack. The fixed star your app navigates by. See you in part 2.