Skip to content

feat(frontend): per-user sign-in; the browser no longer holds the API key (#96) - #115

Merged
amar-python merged 1 commit into
mainfrom
feat/m2e-frontend-sign-in
Oct 26, 2026
Merged

amar-python merged 1 commit into
mainfrom
feat/m2e-frontend-sign-in

Conversation

@amar-python

Copy link
Copy Markdown
Owner

Fixes #96. This is the last part of ART Milestone 2 (BR-36). You decided on 26 Oct: sign-in required; the browser never holds the shared key; the installer creates the first admin.

What changes

Frontend (csv-table-hub-main)

  • Sign-in page. /auth is now a real form: tenant, username, password. It posts to /api/auth/login and keeps the session in sessionStorage, so the session ends when the tab closes.
  • API calls. Every call sends Authorization: Bearer <token>. No call sends X-API-Key, and VITE_API_KEY is removed from the code.
  • Ending a session. A 401 ends the session and returns the user to /auth.
  • Route guard. The upload page and /audit redirect to /auth when nobody is signed in.
  • Header. Shows user · tenant, with the role in the tooltip, and a sign-out button. Sign-out revokes the token on the server too.
  • Error messages. The API's detail errors now show to the user.
  • New files. src/lib/session.ts, src/components/session-menu.tsx, and two test files.

Offline install (#60 tooling)

  • No key in the frontend. The bundle builds the frontend without any API key.
  • First admin. install.sh creates the first tenant and admin. Defaults are main and admin, overridable with TE_TENANT, TE_ADMIN_USER and TE_ADMIN_PASSWORD. A generated password goes to /root/te-initial-admin (mode 600, root only). It is never printed, so it stays out of install.log.
  • Smoke test. Adds two sign-in checks, so there are now 7. It also waits for the frontend to start; see the rehearsal below.

Docs: QUICKSTART (one-time create_tenant_admin.py step, no VITE_API_KEY), ENV_VARIABLES, API_INTEGRATION (who uses bearer and who uses the key), README limitations, env.dev.example, docs/offline-install.md. The API's startup log line no longer says the frontend must send the key.

Evidence

Check Result
vitest 122 passed (107 on main + 15 new)
Same tests with the old key header put back and 401 handling removed both API-call tests fail (as expected)
tsc --noEmit clean
ESLint on new files clean
ESLint on edited files one fewer error than on main
Production build (npm run build) succeeds
Local replica of the CI integration job 297 passed, 0 failed, 0 skipped
Evals p,i,s,e 26/26
DB-free pytest 132 passed
scripts/lint.sh clean

Offline rehearsal of the rebuilt bundle (143 MB, 478 files), inside a network namespace with loopback only:

  • install.sh created tenant main and its admin.
  • The in-install smoke test passed 6 of 7. The frontend check ran before Node had started. That's a real race in the test, now fixed with a wait. Rerun against the same install, it passed 7 of 7.

Real browser (Playwright, same namespace, against the installed app):

  • signed out, / and /audit land on /auth;
  • a wrong password shows the generic error;
  • signing in reaches the upload page, with the header showing admin · main;
  • the page contains no API key, and the token is in sessionStorage;
  • signing out returns to /auth, and / redirects there again;
  • a CSV uploaded through the UI landed in tenant_main.csv_files with 2 rows, and every API call carried a bearer token and no X-API-Key.

Note: GitHub CI doesn't run vitest or the frontend build. The figures above are from this workspace.

After merging

  • Running the app locally needs one tenant admin, created once with the command in QUICKSTART.
  • Existing deployments that set VITE_API_KEY can drop it.

Generated by Claude Code

… key (#96)

The frontend now requires signing in. /auth posts to /api/auth/login and
keeps the session in sessionStorage; every API call sends it as a bearer
token, and no call sends X-API-Key. A 401 ends the session and returns
to /auth; the upload page and /audit redirect there when signed out. The
header shows user and tenant with a sign-out button.

VITE_API_KEY is gone from the code, the offline bundle and the docs. The
offline installer creates the first tenant and admin (password to a
root-only file, not the log) and the smoke test now checks sign-in and
waits for the frontend to start. QUICKSTART gains the one-time
create_tenant_admin step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YPoXzBSj89ZHgw7nfTmbB
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

art ART framework extension work enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

M2e: frontend sign-in and tenant-scoped session (BR-36)

2 participants