crystal-studio-web

Administrator access and private feedback

The Feedback button lets visitors send a bug report, idea or general comment. A name and reply email are optional. Feedback is private to the site’s administrator; no account or payment is needed. Crystal projects and scientific files are not attached to feedback.

Open Crystal Studio Admin to show the password prompt directly. Both /admin and /admin/ work, including after a refresh. This address requires the same server-verified administrator password as the footer Admin link. Opening that footer link normally keeps the current crystal and unsaved work in place; Ctrl/Cmd-click or opening it in a new tab follows the direct admin address.

Private storage was activated on 4 October 2026. The deployed API reports feedback and storage ready; a labeled test submission was saved, reviewed and deleted successfully. Administrator login/logout and enabled feedback forms on desktop and mobile were verified. The public browser key was denied access to both private tables.

The administrator can review paginated submissions, filter by status, mark feedback as new/reviewed/resolved/spam, delete a submission after confirmation, and edit a plain-text site announcement. Website settings also allow feedback collection to be paused. This area manages feedback and the public announcement; it does not edit source code or administer Supabase user accounts.

Server configuration

The frontend never receives the administrator password hash or database secret. Password verification happens in the Python API. A successful login issues a one-hour bearer session kept in the tab’s memory. Logout or closing the admin panel revokes it; a page reload or server restart also requires another login. Feedback and website settings remain in the database across restarts.

Set these environment variables on the existing crystal-studio-api Render service:

Variable Purpose
ADMIN_PASSWORD_HASH Salted scrypt hash generated by the helper below.
SUPABASE_URL The owner’s Supabase project HTTPS URL.
SUPABASE_SECRET_KEY Backend-only sb_secret_... key, or a legacy service_role JWT key.

Keep the existing ALLOWED_ORIGINS and scientific API settings. Put secrets in Render’s environment settings, never in GitHub Actions public variables, frontend/.env.local, a VITE_ variable, source files, or a public repository. Render environment variables, Supabase API keys.

Generate or rotate the hash from crystal_studio_web with the backend virtual environment:

.\backend\.venv\Scripts\python.exe scripts/admin-password.py --output ../.deployment_auth/admin/server-settings.json

The helper prompts twice without echoing the password, preserves other JSON settings and saves only the hash outside the public project. Copy ADMIN_PASSWORD_HASH from that private file to Render and redeploy the API. Rotating it invalidates old sessions when the service restarts.

Private database migration

Apply 202610040001_feedback_admin.sql to the owner’s existing Supabase project with an authorized connection or its SQL editor. It creates only Crystal Studio feedback/settings tables, enables Row Level Security and revokes browser anon/authenticated access. The backend’s private key accesses those tables; public requests can only create validated feedback through the API. Existing account data are unchanged. Supabase RLS.

Obtain a secret API key from the project’s API Keys settings and put it only in Render’s SUPABASE_SECRET_KEY variable. The previously supplied publishable key is for browser account login and cannot activate this private inbox. Deploy the updated backend after setting the variables.

Feedback must use this external database. Render Free does not preserve local files across restarts or deployments; a local SQLite file would lose user submissions. Render Free limits.

Verification

GET /api/community/config exposes only whether admin/feedback are available and the current plain-text announcement. Unconfigured or unreachable storage disables collection with an explanatory message; the API never accepts a submission it cannot save. Admin login can remain available while database setup is incomplete, with inbox/settings controls unavailable.

All inbox and settings routes require the administrator bearer token. Public signup/login sessions do not grant that role. Feedback has bounded fields and a honeypot, and submission/login limits return a retry response. User content renders as text. API errors omit credentials and submitted request bodies.

Run backend tests with .\.venv\Scripts\python.exe -m pytest from backend, and frontend geometry checks with npm.cmd test from frontend. tests/administration.py uses native Python Playwright and installed Chrome against isolated mock responses; it never sends live feedback or tests a real user’s credentials. Production readiness requires verifying the migration, private server variables and storage connection separately. Account email delivery and optional payments retain their status in ACCOUNTS_AND_SUPPORT.md.

After building the frontend, python tests/admin-route.py serves a temporary copy on a plain static server without a fallback route and checks direct entry, refresh, assets, password protection, links, account callbacks and mobile keyboard access. All API responses use independent test credentials. Repeat with --base-path /nested-tool/ after a VITE_BASE_PATH=./ build to check portable hosting. The build emits dist/admin/index.html alongside the workspace entry; it requires no private server route or GitHub Pages rewrite.