prole/docs/onboarding.md
chrisfu 00f0ebec07 Merge claude/crazy-bose-fec256 into main
Bringing the long-running session-feature branch back into main in one
deliberate sweep. The branch carried the cluster work that's been live for
weeks (cross-cluster CNPG metrics, Grafana w/ Google OAuth, supabase
oauth2-proxy, cluster recovery, pg.0.knoe.dev + per-engineer onboarding,
GCS-backed CNPG backups via Workload Identity, the env-contamination
guard, the Junie brief queue, the cnpg-grafana CSRF + memory-request
fixes from today), while main accumulated Junie's parallel knoe-auth
Phase 2 OIDC work (full provider surface: discovery, authorize, token,
userinfo, JWKS, RS256 signing, code exchange, session services).

Key decision: the two branches did COMPETING rebrands off the same
starting point (5ba9b63, 2026-04-27):

  - claude branch (commit b355855, earlier): org.prole.authority.* →
                                              dev.knoe.auth.*
                                              (artifact renamed to
                                              knoe-auth.jar)
  - main (commit 9daa94b, recent): org.prole.authority.* →
                                    dev.knoe.authority.*
                                    (kept "authority" artifact name)

dev.knoe.auth wins: cluster runs from this name, the Maven artifact is
already knoe-auth.jar, and the broader rename is the documented
namespace direction (per ~/.claude/projects/-Users-chrisfu-dev-knoe-db/
memory/MEMORY.md). All of main's recent Phase 2 OIDC content was ported
from authority/src/.../dev/knoe/authority/ into
authority/src/.../dev/knoe/auth/ with package declarations rewritten.

== File-level resolution summary ==

Textual conflicts (4):

  authority/pom.xml
    - Took our artifactId="auth"
    - Took our branch's removal of spring-security-kerberos-client
      (verified: Junie's Phase 2 OIDC code does not import it; the dep
      was already-dead config)

  docs/pipeline-phases.md
    - Took our branch's "Phase 1 not started" status. Main had a
      misplaced " Complete" with a knoe-auth-Phase-1 commit ref
      in the autobuild Phase 1 section — different domain.

  docs/plans/knoe-auth-round-1.md
    - Took our branch's dev.knoe.auth file table (vs main's
      dev.knoe.authority listing). Pure rename mismatch.

  supabase/helm/knoe-supabase/templates/kong/config.yaml
    - Took our branch's onboard route + plain dashboard wiring.
      Main had an oauth2proxy.enabled toggle that put oauth2-proxy as
      a Kong upstream — but the deployed architecture (commit 25f1b2e)
      has oauth2-proxy in FRONT of Kong, not behind. Main's wrapper
      reflected an architecture that was never deployed.
    - Took our branch's removal of basic-auth from dashboard route
      (queue #15 brief still tracks the matching values.yaml /
      kong/deployment.yaml cleanup).

Java tree reconciliation (44 file-pairs):

  20 dual-path source files + 2 dual-path tests
    Body-identical between main's authority/ and our branch's auth/
    after stripping package decls — main's commit 9daa94b was a pure
    rebrand. Took our branch's auth/ version for all 22.

  8 main-only source files (Phase 2 OIDC), ported into auth/:
    web/JwksController.java
    web/OidcAuthorizeController.java
    web/OidcDiscoveryController.java
    web/OidcTokenController.java
    web/OidcUserInfoController.java
    session/OidcCodeService.java
    session/OidcTokenService.java
    session/SessionService.java

  12 main-only test files, ported into auth/:
    HealthControllerTest.java
    enroll/EnrollValueTypesTest.java
    enroll/EnrollmentControllerTest.java
    enroll/TotpServiceTest.java
    kerberos/KadminClientTest.java
    kerberos/KerberosSpnegoResultTest.java
    web/LoginControllerTest.java
    admin/AdminControllerTest.java
    user/PrincipalNormalizerTest.java
    regression/IdentityRegressionTest.java
    session/OidcCodeServiceTest.java
    session/SessionServiceTest.java

  Port mechanics: read main:authority/...<file> via git show, then sed
  rewrite `package dev.knoe.authority` → `package dev.knoe.auth` and
  `import dev.knoe.authority` → `import dev.knoe.auth`. Body content
  unchanged.

  authority/src/main/java/dev/knoe/authority/ — DELETED (duplicate)
  authority/src/test/java/dev/knoe/authority/  — DELETED (duplicate)

== Verification ==

- grep -rln '<<<<<<<' across .java/.md/.yaml/.yml/.sh/.xml/.tpl: clean
- find authority/src -path '*/dev/knoe/authority*': empty (subtree gone)
- grep 'package dev.knoe.authority' across repo: clean
- bash -n install.sh deploy.sh etc/preflight_kubecontext.sh: clean
- git ls-files -u | wc -l: 0 unmerged paths
- helm lint supabase/helm/knoe-supabase: pre-existing failure on
  studioIngress.enabled undefined in values.yaml (introduced by Junie
  on main; unrelated to this merge — flagging as follow-up).

== Followups (carried into TODO ranked queue or noted here) ==

  - helm lint failure: studioIngress block in values.yaml is missing
    enable flag; templates/studio/{ingress,oauth2proxy-deployment,
    oauth2proxy-service}.yaml all reference studioIngress.enabled with
    no default. Pre-existing on main; not introduced by this merge.
  - The five Junie briefs filed on this branch are now reachable from
    main at docs/plans/junie/{02,06,07,13,15}-*.md. Junie can pick them
    up in any order.
  - knoe-auth Phase 2 OIDC source (now at dev.knoe.auth.*) is not yet
    deployed to the cluster. Deployment is its own task.
  - The branch claude/crazy-bose-fec256 stays in place (worktree at
    .claude/worktrees/crazy-bose-fec256 may have ongoing context for
    Claude Code sessions). Safe to delete once next session starts
    cleanly from main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 16:39:10 -07:00

5.6 KiB

Engineer onboarding — first-day checklist

Welcome. This doc gets you from "I just got an onboarding link" to "psql is open and I'm productive". Should take ~5 minutes.

Phase 1 (current). Each engineer has a per-name postgres role with a temp password (24h) delivered via a one-time link. Phase 2 (queued) replaces the password mechanism with libpq OAUTHBEARER (Google sign-in). Your role name persists; only the connection string changes when Phase 2 lands.


What you should have

  1. An onboarding link that looks like https://db.0.knoe.dev/onboard.html#user=...&pw=...&exp=..., delivered by chrisfu via either:
    • A Gmail message to your @knoey.com mailbox, or
    • A QR code shown on screenshare during a Signal call.
  2. A clone of the knoe-db repo.

If you don't have either, ping chrisfu.


Click the URL (or scan the QR with your phone camera). The page at db.0.knoe.dev/onboard.html decodes the URL fragment client-side and displays:

  • Your temporary password — with a [Copy] button
  • Your psql connection string — pre-filled with your role name, also [Copy]
  • A bootstrap one-liner that fetches the CA cert and connects you
  • Inline \password rotation instructions

Save the password to your personal 1Password (or whichever password manager you use). The page strips the password from your browser history on first render, but DO NOT close it before saving — the page is one-shot.


Step 2 — Connect and rotate

Clone the repo if you haven't, then connect:

git clone git@git.knoe.dev:knoey.dev/knoe-db.git
cd knoe-db
psql "host=pg.0.knoe.dev port=5432 user=$YOUR_USERNAME dbname=postgres \
      sslmode=verify-full sslrootcert=etc/knoe-db-ca.crt"

Paste the temporary password when prompted.

Rotate immediately:

postgres=> \password
Enter new password: <type a strong password you generate locally>
Enter it again:     <repeat>
postgres=> -- save the new password to your personal 1Password.
postgres=> -- everything from here uses YOUR password.

Why immediately? The temp VALID UNTIL is 24h; if you don't rotate before then, you'll be locked out (chrisfu can rerun the onboard script to issue a fresh temp).


Step 3 — What you can do as knoe_developer

Your role is a member of the knoe_developer group. Grants:

Schema Permission Notes
knoe SELECT, INSERT, UPDATE, DELETE Application schema
public SELECT, INSERT, UPDATE, DELETE Same
auth SELECT only Read-only on Supabase GoTrue tables
storage SELECT only Read-only on Supabase storage tables
extensions USAGE Lets you reach extensions.pg_stat_statements etc.

What you can't do:

  • Drop / truncate auth.* or storage.* (read-only on those by design).
  • CREATE ROLE, CREATE EXTENSION (postgres superuser only).
  • Connect from outside the cluster as postgres, supabase_admin, etc. (those roles are pinned to RFC1918 by pg_hba.conf).

Need broader access? File an issue or ping chrisfu — easier to extend the group than mint per-engineer overrides.


Step 4 — Rust apps (if applicable)

Same connection string in sqlx / tokio-postgres / deadpool-postgres:

let url = format!(
    "postgres://{user}:{password}@pg.0.knoe.dev:5432/postgres\
     ?sslmode=verify-full&sslrootcert={ca}",
    user = std::env::var("KNOE_PG_USER")?,
    password = std::env::var("KNOE_PG_PASSWORD")?,
    ca = std::env::current_dir()?.join("etc/knoe-db-ca.crt").display(),
);
let pool = sqlx::PgPool::connect(&url).await?;

For deployed services (not your laptop): Phase 2 swaps the user/password env vars for an OIDC token. The connection string skeleton stays the same.


Step 5 — Studio access (web UI, optional)

Open https://db.0.knoe.dev/ in any browser, sign in with your @knoey.com Google account. Studio is the same database; you can use it for ad-hoc queries, table inspection, RLS rule editing. Most of what you need is in the SQL editor.


Troubleshooting

  • pg_hba.conf rejects connection ... no encryption — you set sslmode=disable. Use verify-full (with sslrootcert=etc/knoe-db-ca.crt) or at minimum require.

  • password authentication failed — wrong password (typo when copy-paste, or temp expired). Run psql with \password once you're in, OR ping chrisfu to rerun the onboard script.

  • role "<u>" is not permitted to log in — your VALID UNTIL lapsed. Ask for rotation.

  • Connection times out — DNS for pg.0.knoe.dev may not have propagated on your network yet. Try dig pg.0.knoe.dev. Should resolve to 34.106.156.196 (or whatever the current LB IP is).

  • server certificate for "..." does not match host name "pg.0.knoe.dev" — you're using verify-full but the CA cert in your repo is stale (CNPG rotated the CA). git pull and try again, or fetch the fresh cert from chrisfu.


  • docs/db-access.md — the underlying access architecture (LB, pg_hba, role grants, Phase 2 plan).
  • The plan file (live, not in git) at ~/.claude/plans/we-re-continuing-work-on-happy-toast.md for chrisfu — has the design rationale for why this delivery channel was chosen over a shared vault.
  • etc/onboard_engineer.sh — the script chrisfu runs to provision your role and emit your URL. Same script handles --rotate and --revoke.