Skip to content

Cannot issue managed-user tokens on v1.20.0: bootstrap --issue-token fails audit validation, dashboard returns 403 #1122

Description

@70miboy

Summary

On a fresh self-hosted engram cloud serve deployment (v1.20.0, the latest stable release), it is impossible to issue the first managed-user token. Both available paths fail, which leaves the managed-user / project-grant system unreachable: the schema, the UI and the deny-by-default policy are all there, but no principal can ever authenticate.

Environment

  • engram 1.20.0 (linux_amd64 official release tarball, checksum verified)
  • Linux Mint 22.3 (Ubuntu 24.04 base), kernel x86_64
  • PostgreSQL 16.15 (distro package)
  • Auth mode: ENGRAM_CLOUD_TOKEN + ENGRAM_JWT_SECRET + ENGRAM_CLOUD_TOKEN_PEPPER + ENGRAM_CLOUD_ADMIN all set; ENGRAM_CLOUD_ALLOWED_PROJECTS set to a single project

Path 1 — CLI: bootstrap --issue-token fails on its own audit validation

$ engram cloud bootstrap admin --username tomas --email <redacted> \
    --grant-project <project> --issue-token my-machine

engram: cloud bootstrap admin: create token with completion audit:
cloudstore: auth audit insert failed:
cloudstore: sensitive auth audit metadata is not allowed: issued_token

The command writes the audit entry with an issued_token key in metadata, and the store's own validator rejects that key as sensitive.

Partial-success side effect: the user, principal and project grant are created and persist; only the token issuance fails. So the command is not atomic — re-running it hits a duplicate user instead of retrying the token.

cloud_human_users      -> 1 row  (username: tomas)
cloud_principals       -> 1 row  (kind: human, role: admin, enabled: t)
cloud_project_grants   -> 1 row  (project granted)
cloud_principal_tokens -> 0 rows

Path 2 — Dashboard: Create Token returns 403

POST /dashboard/admin/users/<id>/tokens (form on the managed-user detail page) responds 403, and no row is inserted.

The reason appears in cloud_auth_audit_log: signing into the dashboard with ENGRAM_CLOUD_ADMIN records

actor_source        = legacy_env_admin
actor_principal_id  = NULL
action              = dashboard.login
outcome             = success
metadata            = {"role": "admin", "source": "legacy_env_admin"}

Issuing a credential presumably requires an actor with a principal identity, and the env-var admin has none. That guard seems intentional and reasonable on its own — but combined with Path 1 it closes the loop.

Why this is blocking

  1. Creating a managed-user token requires being authenticated as a managed user
  2. Authenticating as a managed user requires a token
  3. The only bootstrap path for the first token is bootstrap --issue-token, which fails at (1)

Net effect: on 1.20.0 a self-hosted deployment can only ever use the single shared ENGRAM_CLOUD_TOKEN. The per-user model (deny-by-default grants, per-principal tokens, auth audit trail) is present in the schema and the dashboard but cannot be activated.

This matters for the intended use case: two people sharing one server, where one of them should only see one project. Today the shared token grants access to everything in ENGRAM_CLOUD_ALLOWED_PROJECTS, so the only workaround is to keep the second person off the server entirely.

Expected behavior

bootstrap admin --issue-token should print the raw token once and persist its hash, without the completion-audit write rejecting the operation. Ideally the audit entry should record token metadata (id, label, actor) rather than the token material itself.

Notes

  • Everything after 1.20.0 is a release candidate (v2.0.0-rc.1rc.9), so there is no stable version to upgrade to. If this is already fixed on the 2.0 line, it would help to know whether a 1.20.x patch is planned.
  • ENGRAM_CLOUD_TOKEN_PEPPER is required for --issue-token but is not listed in engram --help; it only surfaces as an error message when the command fails. Worth documenting alongside the other ENGRAM_CLOUD_* variables.
  • Similarly, ENGRAM_CLOUD_HOST defaults to 127.0.0.1, which makes a self-hosted server unreachable even from within the operator's own private network. Not a bug, but an easy trap on first deploy.

Happy to test a patch against this deployment.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions