Passkey Authentication and UI access

Passkey Authentication and UI access

Human access to the pico-engine developer UI is passkey-based. There are no shared passwords and no central user directory: you prove who you are with a WebAuthn passkey (Touch ID, Windows Hello, a phone, or a security key), and the engine issues a session that unlocks the UI and the internal /c/* API.

Each account is tied to exactly one root pico. That root is your agent in the mesh — the pico you manage after sign-in.

← Back to Identity


What a passkey gives you

After you…

You get…

After you…

You get…

Register

A new account, a new root pico, and a signed-in session

Sign in

A session scoped to your account’s root and its descendants

Claim (legacy upgrade)

Your existing root linked to your first passkey

The session is stored in an HTTP-only cookie (pico-session). It lasts 30 days by default and is renewed when you sign in again. Logout clears it.

Sign-in is usernameless: the browser or OS shows passkeys that match this engine; you pick one and complete the biometric or PIN step. You do not type an email or password.


First visit: which screen you see

The UI chooses a flow based on engine state:

Fresh engine (no accounts, no roots)

You see Register with passkey only. Registration creates your account and root pico in one step. This first account is bootstrap — no invite or setup token required.

Optional display name labels your mesh in the UI (defaults to something like pico-abc123 if left blank).

Existing mesh, no auth yet (legacy upgrade)

If the engine already has a root pico from before passkey auth was enabled, you see Claim with passkey instead of register or login. Claim links your passkey to that existing root so your picos and rulesets are preserved.

Normal registration is blocked until claim completes — registering would create a second, orphan root.

Engine with accounts (normal operation)

You see Sign in with passkey. If the operator has enabled open registration, a Create another account link is also shown.

Invite link (?invite=…)

A signed-in user can create a single-use invite link (Settings → Invite). When you open that link:

  1. The UI checks that the invite is valid and not expired (7 days by default).

  2. You see Register with passkey even though the engine already has accounts.

  3. After registration, the invite is consumed and cannot be reused.

If the invite is invalid or expired, the UI shows a warning and registration via that link is not allowed.


Using the UI after sign-in

Once authenticated, the developer UI shows your root pico and its subtree. From there you can:

  • Browse and manage picos, rulesets, channels, and subscriptions

  • Open Settings (gear icon) to manage passkeys and invites

  • Use Logout to end the session

All UI API calls send the session cookie automatically. If the session expires or is cleared, you return to the sign-in gate.

Scope of access

Your session is bound to one root pico. You can work with that root and any pico in its descendant tree. Requests to picos outside your tree are rejected.

This is separate from OAuth, which external apps use on /sky/*. Passkeys are for humans using the engine UI and internal APIs — not for webhook senders or Home Assistant.

When you approve an OAuth app (Authorization Code flow), you must already be signed in. If you were redirected to sign in first, the UI sends you back to the authorize step afterward (oauth_return).


Settings

Open Settings on the main page.

Passkeys

  • List — passkeys registered for your account (label and date).

  • Add passkey — enroll another device or security key on the same account. Useful before replacing a laptop or phone.

  • Remove — delete a passkey you no longer use.

You cannot remove the last passkey on an account. Add another first, then remove the old one.

Adding a passkey does not create a new root or account — it adds another way to sign in to the same account.

Invite links

Available when signed in. Use this when the engine does not allow open self-signup (the default).

  1. Optionally enter a label (shown to the invitee, e.g. “Alice”).

  2. Click Create invite link.

  3. Copy the link and send it to the person who should register.

Each link is single-use and expires after 7 days. The invitee opens the link, registers with a passkey, and gets their own account and root pico.

When self-signup is enabled, anyone can register from the login screen without an invite. Invites still work for controlled onboarding.


What requires a session

Surface

Who

Authentication

Surface

Who

Authentication

Developer UI

You

Passkey → session cookie

/c/*

UI and in-engine HTTP

Session cookie (see localhost note below)

/auth/*

Registration, login, session management

Ceremony during WebAuthn; session for management routes

OAuth app registration, channel credential management

You (signed in)

Session cookie

/c/* is the internal channel HTTP binding. It is not the public API for third parties. External integrators use /sky/* with OAuth (see sibling pages).

Localhost and in-engine HTTP

By default, requests to /c/* from localhost are allowed without a session. That supports KRL rules that POST to http://localhost:…/c/… from the same machine.

Operators can disable this by setting PICO_ENGINE_ALLOW_LOCALHOST_C=0, which requires a passkey session even from localhost. See Environment variables.


Operator configuration

These environment variables affect human auth:

Variable

Effect

Variable

Effect

PICO_ENGINE_BASE_URL

Public URL of the engine (scheme + host + port). Must match what users type in the browser. Used as the WebAuthn relying party origin — a mismatch causes registration or sign-in to fail.

PICO_ENGINE_ALLOW_SELF_SIGNUP

Set to true or 1 to allow anyone to register additional accounts after bootstrap. Default is off (login only; bootstrap, claim, and invites still work).

PICO_ENGINE_ALLOW_LOCALHOST_C

Set to 0 to require a session on /c/* from localhost. Default allows localhost without a session.

Behind HTTPS, set PICO_ENGINE_BASE_URL to your https://… URL (typically via a reverse proxy). The session cookie is marked Secure when the base URL uses HTTPS.


Troubleshooting

Passkey registration or sign-in fails immediately

  • Confirm PICO_ENGINE_BASE_URL matches the URL in the browser bar (including https:// and hostname).

  • On localhost, use http://localhost:PORT consistently — not 127.0.0.1 in one place and localhost in another (WebAuthn treats them as different relying parties).

“Self-signup is disabled” when registering

  • The engine already has accounts and open registration is off. Ask an existing user for an invite link, or have the operator set PICO_ENGINE_ALLOW_SELF_SIGNUP=true.

“Claim with passkey” instead of login

  • The engine has a pre-auth root mesh waiting to be linked. Complete claim once; afterward you use normal sign-in.

Locked out

  • There is no password reset. Recovery requires another passkey still registered on the account (if you added a backup), or operator intervention on the engine data store. Add a second passkey in Settings before retiring a device.

OAuth authorize sent me to sign in and then stopped

  • After sign-in, the UI should redirect back to the authorize URL. If it does not, open the authorize link again while signed in.


How it fits the identity model

You ──passkey──► account + root pico ──session──► UI and /c/* └── (future) DID/agent identity outward to the mesh

Passkeys answer “Is this the right human for this root?” Channel policy and OAuth answer “What may this caller do?” on their respective surfaces.