Staff sign in
Sign in with the email and password you set when accepting your Idunox invitation. A one-time code will be sent to your email on every sign-in.
A tenant is one customer or lab organization — the isolation boundary for API keys, pack entitlements, and all submission data. Use Create tenant to register a new organization. See Glossary → Tenant.
A credential is an API key tied to one tenant. Partners send it as X-Api-Key on api-test.idunox.com. See Glossary → Credential.
Partner portal — primary onboarding
Select a tenant above. Invitations are scoped to that tenant only — the invite link includes the tenant id.
Default path: send an invitation so the partner’s team signs in at partner-test.idunox.com/management/api-keys, sets their password, and creates and rotates API keys themselves. You do not need to handle plaintext secrets — the portal shows each key once, same as staff issuance.
| Name | Status | Last login |
|---|
Staff-issued API keys — backup only
Use Issue API key (backup) only when the partner cannot use the portal — e.g. invitation email failed, emergency unblock, or internal lab testing. Prefer resending the invitation first. Revoke and rotate still apply to keys created here or in the portal.
| Name | Prefix | Status | Expires | Created |
|---|
Staff admins who can sign in to this portal. You cannot delete/deactivate your own account or the last active admin. Tenant & submission deletions require a second admin to approve — keep at least two active.
| Name | Role | Status | Last login | Actions |
|---|
A submission is one lab result ingest request from a partner — scoped to the tenant derived from their API key, not from body fields alone. See Glossary → Submission. Rows with status REJECTED are POSTs rejected at intake (4xx) — sourced from the platform audit log, retained 90 days, with the error code in the Error column (hover for field-level reasons). 401/429 requests are not listed (see the partner-submission-failure runbook).
| Actions | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
Submission activity over the selected window — platform totals and per-tenant breakdown. See Glossary → Stats.
Load stats to see the dashboard.
Every staff change in this portal, and every key change a partner makes in the partner portal, newest first: who did it, when, to what, and the reason given. The list is read-only. Each row was written in the same database transaction as the change it records. Partner submission rejections are on the Submissions tab.
| Time | Actor | Action | Tenant | Resource | Reason | Details |
|---|---|---|---|---|---|---|
| Open this tab to load the audit log. | ||||||
Definitions for terms used across this staff portal and the andres-test partner API.
-
TenantOne customer or lab organization in the platform. Every API key, submission, result, and report artifact belongs to exactly one tenant. Tenants are the isolation boundary — partners never share data across tenants.
For partner-facing demos and docs verification, prefer one multi-pack customer tenant over many throwaway tenants. Do not merge tenants by editing JSON alone: credentials, subjects, submissions, jobs, results, artifacts, webhooks, idempotency keys, and audit logs are tenant-scoped records. -
Credential (API key)A secret issued to a tenant for machine-to-machine access. Stored as a hash + prefix only; the full secret is shown once at creation. Sent on each request as header X-Api-Key. Inherits the tenant’s pack entitlements.
-
Internal keyAn API key that Idunox uses inside a customer tenant, for deploy probes, release gates and audits. Mark it on Credentials with an audit reason. The partner portal then hides the key and every submission, result, rejection and count made with it. Nothing is deleted, and the partner cannot revoke or rotate the key. A rotated internal key stays internal. An internal key is never deleted, because its traffic would show to the partner again: revoke it instead. Stats can include, exclude or isolate internal traffic.
-
SubmissionA single POST /v2/submissions ingest (the only partner contract; /v1 was removed on 2026-10-09) — partner blood markers and metadata entering the pipeline. The tenant is determined from the API key, not from partner IDs in the JSON body.
-
SlugA short, URL-safe identifier for a tenant (lowercase letters, numbers, hyphens). Used in key labels, scripts, and ops — e.g. health-yourself for Health Yourself.
-
PackA licensed Idunox product — Health Yourself, Pilot, or Care. A pack defines the marker intake scope (questionnaire + blood analytes), wellbeing outcomes, model bundle, report layout, and which partner documentation slices a tenant may view.
What you assign to a tenant: a pack (product license), stored in tenant.metadata.assignedPackIds. The platform may dual-write derived input panel IDs beside them, but Staff UI and /v2 entitlement always use pack IDs (Care must not collapse to Pilot in the picker).
Where used: pack guard on POST /v2/submissions (403 PACK_NOT_ASSIGNED when the requested pack is not assigned); partner docs entitlement by pack ID; report template and model routing from the accepted pack snapshot. Customer tenants usually have one pack; lab tenants are for internal parity only. -
Panel IDStable machine identifier for a pack's input marker vocabulary, e.g. iduscore_health_yourself, iduscore_pilot. Care currently shares Pilot's input panel while remaining a distinct licensed pack ID (iduscore_care).
Where used: derived operational metadata dual-written beside assignedPackIds; never accepted as a public /v2 selector. Partners POST the /v2 wire with required packId plus Q/B guide ids — not panelId. -
Partner API versionThe partner API is a single documented contract — /v2; the URL path is the contract and no format headers are used. All andres-test partners integrate on /v2, and the Partner Portal API reference exposes pack selection only (there is no API-version selector). The legacy /v1 partner API and its format headers were removed from the runtime on 2026-10-09; every /v1 partner path answers 404. The portal routes under /v1/partner and /v1/admin are separate and unchanged. Staff do not choose a tenant-level “Partner API contract” dropdown.
-
Report JSON versionDownloadable JSON report schema. On /v2 it is the normalized partner_report_json_v2, fixed server-side by packId (both HY packs emit it); staff do not choose it in Admin, and /v2 uses no format header. (HY results stored before the J-R26 core deploy also carry a partner_report_json_v1 artifact; new HY results store only v2. No partner route has served v1 since /v1 was removed on 2026-10-09.) The deployed v2 artifact is normalized: areas stay in wellbeingAreas[], all Q/B/D markers and marker-to-area ranks live in markers[].areaContributions[], and action ranks live in actions[].priority plus actions[].supportedAreas[].rankInArea.
-
Panel (marker profile)The full marker and model profile behind a pack: required blood marker guide ids (B### on partner wire), questionnaire Q001–Q037, inference model bundle, and report template. Docs often say “14-marker panel” or “13-marker panel” for the blood analyte list only — that list is part of the panel profile, not the whole product. Do not confuse with UI “tabs” in this portal (those are navigation panels).
Where used: validation presets (panel-blood-marker-presets.js), pack guard inference, parity fixtures, and pack-specific input-data guides. One pack ↔ one panel profile today; panel ID is the join key. -
Type (Customer vs Lab)Customer — real partner-style tenant (e.g. Health Yourself). Lab — internal andres-test tenant for gates and pack parity; not for production partner traffic.
-
PrefixThe first characters of an API key stored for support and UI display (e.g. idu_prod_sk_… for production keys, idu_dev_sk_… for dev). Lets staff identify a key without revealing the full secret.
-
Status (credential)Active — key accepts API calls. Revoked — key rejected immediately; use when rotating or deprovisioning access.
-
Partner submission IDThe partner’s own identifier for a submission (their idempotency / trace id). Distinct from our internal submission UUID.
-
Audit reasonRequired note on create, update, revoke, and pack changes — who did what and why. Stored in row metadata today (lastAdminChangeReason); a separate audit_logs table (model AuditLog) also exists, populated by the platform pipeline.
-
API base URLPartner integration endpoint for andres-test: https://api-test.idunox.com (version-neutral host; the current contract is /v2, e.g. /v2/submissions). Docs live in the partner portal at partner-test.idunox.com/docs.
-
StatsDashboard cards: platform totals (submissions, completion rate, active keys) plus per-tenant breakdown over the selected day window. The Internal keys menu decides whether traffic from internal keys counts; the heading names the choice.
-
Staff sign-inEmail invitation → set password → sign in with email, password, and a mandatory one-time code sent by email on every login. Production URL: admin-test.idunox.com. Local dev: bash scripts/deploy/phase19_admin_ui_local_dev.sh → port 8791.
Staff guide for the andres-test Admin Portal. For term definitions see Glossary.
What this portal does
Idunox staff use this UI to onboard partners on the andres-test stack only: create tenants, assign biomarker packs, invite partners to the self-service portal, and monitor submissions. Partners integrate against api-test.idunox.com — not production Rakesh URLs.
Current API docs are pack driven: assign packs here, then partners select their pack in the Partner Portal API reference and integrate on /v2 (there is no API-version selector). Staff no longer choose tenant-level Partner API contract or Report JSON version dropdowns.
Current GCP stack status: partner traffic uses api-test.idunox.com, and the deployed V2 JSON artifact is the normalized partner_report_json_v2 model. Use the Partner Portal end-to-end examples and API reference to verify each pack/version combination.
How to open this UI
- Production (staff): https://admin-test.idunox.com — sign in with your invited staff account (email, password, and email OTP).
- Local dev (recommended): run bash scripts/deploy/phase19_admin_ui_local_dev.sh then open http://127.0.0.1:8791/ — serves latest disk HTML and proxies API to Cloud Run.
- Cloud Run proxy: run bash scripts/deploy/phase19_admin_ui_proxy.sh then open http://127.0.0.1:8787/ — serves UI bundled in the deployed image.
- Do not open admin-ui.html as a static file — API calls will fail with 404.
Tabs at a glance
- Tenants — list organizations; search, sort, and filter columns; Create tenant and a per-row edit (pencil) / delete (trash) action.
- Credentials — Send invitation (primary onboarding); staff Issue API key (backup), plus per-key rotate (circular-arrows icon) and delete (trash) actions.
- Submissions — load recent ingests (newest first by submission time), then sort by column, filter per column, or search all columns (client-side on loaded rows). Each row leads with the submission time (YYYY-MM-DD HH:MM:SS, local), tenant, and the API key used.
- Stats — dashboard: platform totals and per-tenant activity over N days.
- Glossary — definitions (tenant, pack, credential, …).
- Help — this guide, onboarding steps, troubleshooting.
Modal dialogs (common pattern)
Most write actions use a modal instead of a separate page — same pattern across tabs:
- Tenants → Create tenant — identity, packs (0–all), customer/lab type, audit reason.
- Tenants → row edit (pencil) — change name, slug, type, and assigned packs (0–all) + audit reason.
- Credentials → Send invitation — partner email invite (72h link; M365 when configured).
- Credentials → Issue API key (backup) — staff-issued secret (shown once); use only when portal path fails.
- Credentials → row rotate (circular arrows) / delete (trash) — audit reason required.
Tenant consolidation guidance
For partner-facing use, prefer a single customer tenant with all licensed packs assigned. Test and E2E tenants can be kept for gates, but should not be used as partner accounts once a canonical multi-pack tenant exists.
Consolidating existing tenants is a database migration: move or retire credentials, portal users, subjects, submissions, jobs, results, artifacts, webhooks, idempotency keys, and audit logs. Do not “centralize” by only changing assignedPanelIds.
Tenants & Submissions — search and filter
Both table tabs share the same pattern:
- Search all columns — matches visible text plus ids (tenant id on Tenants; internal submission id on Submissions).
- Filter row — type under each column header.
- Sort — click a column header; click again to reverse. Tenants default to name A→Z; Submissions default to newest first.
- Row count — shows filtered vs total when filters are active.
Submissions also has a tenant dropdown and Load to fetch from the API (max 200); sort/filter/search apply to loaded rows only.
Onboard a new customer tenant
-
1
Confirm the licensed pack
Default: assign every pack the customer has licensed (often one). Health Yourself → Health Yourself; add Pilot/Care when contracted.
-
2
Create the tenant
Open Tenants, click Create tenant (modal). Enter legal name and slug (e.g. acme-health). Pick the pack and Customer type. Audit reason is required.
-
3
Send a partner-portal invitation
Go to Credentials, select the tenant, click Send invitation. The partner receives email with a link to partner-test.idunox.com/management/api-keys, sets a password, then creates their own API keys in the portal.
-
4
Partner self-service keys (or staff backup)
Normally the partner creates keys in the portal — you never see the plaintext secret. If the portal is unavailable, use Issue API key (backup) on Credentials and deliver the one-time secret over a secure channel.
API base URL: https://api-test.idunox.com (version-neutral host; current contract /v2, e.g. POST /v2/submissions)
Partner portal: https://partner-test.idunox.com/management/api-keys
Partner docs: https://partner-test.idunox.com/docs -
5
Verify integration
Submit a canonical fixture with X-Api-Key only against api-test. On Submissions, click Load, then search or filter to find the ingest. Check Stats for totals. Submitting a packId the tenant is not assigned returns 403 PACK_NOT_ASSIGNED.
-
6
Optional: webhook
Configure callback URL via tenant metadata (API PATCH) or seed scripts. Andres-test default uses the internal webhook sink.
Partner portal invitations
- Primary path: Credentials → Send invitation — partner sets password via email link and creates keys at partner-test.idunox.com/management/api-keys.
- Resend: Pending invites show Resend invite in the portal users table (audit reason required).
- Email not sent: Configure M365 Graph via bash scripts/deploy/phase19_setup_partner_portal_email.sh, or copy the invite URL from the flash message and share securely.
- Backup keys: Issue API key (backup) only when the partner cannot use the portal.
Rotate or delete a key
- Rotate (circular-arrows icon): partner rotates in the portal (or staff uses backup issuance) → confirm traffic on the new key → delete the old key on Credentials (audit reason required).
- Delete (trash icon): Credentials tab → trash icon → confirm in the modal (audit reason required). The credential record is removed and the key stops working immediately. An internal key is never deleted: its row shows Revoke instead.
- Two active keys per tenant during overlap is supported.
Troubleshooting
| Symptom | What to check |
|---|---|
| 403 PACK_NOT_ASSIGNED | Submitted packId is not in tenant assignedPackIds — see Glossary → Pack |
| 401 on partner API | Key revoked, wrong key, or expired credential |
| 403 Forbidden on this UI | Sign in with your staff account, or complete your invitation first. If the page loads but API calls fail, sign out and sign in again. |
| 401 Unauthorized on API calls | Session expired — sign in again (email, password, then email OTP). |
| Invitation link invalid | Ask another staff admin to resend your invitation from the staff-users API or seed script. |
| Invitation email not received | Check portal users status; resend invite; run phase19_setup_partner_portal_email.sh or share invite URL from admin response |
| No submissions in table | Submissions tab → click Load; widen limit; clear search/filters |
| Raw JSON authentication required instead of login page | GET / must return HTML — redeploy phase19_deploy_admin_api.sh if this recurs. |
| 404 error banner on load | Use phase19_admin_ui_local_dev.sh or Cloud Run proxy — not static admin-ui.html |
| Empty Stats dashboard | Click Refresh dashboard; widen day window; redeploy admin-api if message persists |
Support
For any issue with this portal, contact info@idunox.com.
External links
- Staff admin: admin-test.idunox.com
- Partner portal: partner-test.idunox.com/management/api-keys
- Partner API: api-test.idunox.com
- Partner docs: partner-test.idunox.com/docs
Repo runbooks: docs/runbooks/andres-test/PARTNER_ONBOARDING_RUNBOOK.md, PARTNER_PORTAL_API.md, STAFF_ADMIN_AUTH.md