rebrand Scirium docs (Wall-O -> Scirium) + add v1/v2 documentation package

This commit is contained in:
root
2026-08-16 09:24:58 -04:00
parent 0424b2954a
commit 64cf1043e7
11 changed files with 453 additions and 82 deletions
+30 -30
View File
@@ -1,4 +1,4 @@
# Wall-O: Deployment, White-Label, and Phase 0 Build Plan
# Scirium: Deployment, White-Label, and Phase 0 Build Plan
Scope: multi-tenant internal staff knowledge-base chat. Rocket.Chat is chat transport only (one workspace per tenant). The orchestrator is a multi-tenant FastAPI service that owns tenancy, agents, kb_scope, the M365 connector, retrieval, and LLM. Strictly internal staff knowledge. No patient records, no PHI.
@@ -10,13 +10,13 @@ Canonical entities: tenant_id (a practice), channel_id (a knowledge domain with
| Component | Host | Port | Scope | Scales per tenant |
|---|---|---|---|---|
| Caddy reverse proxy | wall-o host | 80 / 443 | shared | single process, per-tenant site blocks |
| Orchestrator (FastAPI, ASGI via uvicorn worker) | wall-o host | 127.0.0.1:8000 | shared | 1 instance; add workers or a second host behind a load balancer |
| Orchestrator DB (Postgres + pgvector) | wall-o host | 127.0.0.1:5432 | shared | 1 primary; promote to a replica for read scale |
| Rocket.Chat workspace (tenant N) | wall-o host | 127.0.0.1:3010N | per tenant | 1 Docker Compose stack per tenant, no shared state |
| MongoDB (tenant N, Rocket.Chat native store) | wall-o host | 127.0.0.1:2710N (loopback only) | per tenant | 1 Mongo per tenant, isolated volume |
| Branding assets (logo, favicon, custom CSS, PWA shell) | wall-o host | /var/www/wall-o/ | per tenant | static files, chmod 644, no process |
| M365 connector (orchestrator module) | wall-o host | n/a (in-process) | shared | horizontal with the orchestrator |
| Caddy reverse proxy | scirium host | 80 / 443 | shared | single process, per-tenant site blocks |
| Orchestrator (FastAPI, ASGI via uvicorn worker) | scirium host | 127.0.0.1:8000 | shared | 1 instance; add workers or a second host behind a load balancer |
| Orchestrator DB (Postgres + pgvector) | scirium host | 127.0.0.1:5432 | shared | 1 primary; promote to a replica for read scale |
| Rocket.Chat workspace (tenant N) | scirium host | 127.0.0.1:3010N | per tenant | 1 Docker Compose stack per tenant, no shared state |
| MongoDB (tenant N, Rocket.Chat native store) | scirium host | 127.0.0.1:2710N (loopback only) | per tenant | 1 Mongo per tenant, isolated volume |
| Branding assets (logo, favicon, custom CSS, PWA shell) | scirium host | /var/www/scirium/ | per tenant | static files, chmod 644, no process |
| M365 connector (orchestrator module) | scirium host | n/a (in-process) | shared | horizontal with the orchestrator |
Port formulas: tenant N Rocket.Chat = 30100 + N, tenant N MongoDB = 27100 + N. Tenant 1 (Wall Orthodontics) uses 30101 and 27101.
@@ -24,16 +24,16 @@ URL pattern (ITPP convention):
| Surface | URL |
|---|---|
| Orchestrator API | https://api.wall-o.itpropartner.com |
| Orchestrator admin console | https://wall-o.itpropartner.com |
| Tenant N chat + branded PWA | https://<tenant-slug>.wall-o.itpropartner.com |
| Orchestrator API | https://api.scirium.itpropartner.com |
| Orchestrator admin console | https://scirium.itpropartner.com |
| Tenant N chat + branded PWA | https://<tenant-slug>.scirium.itpropartner.com |
Caddy is the TLS edge. Each tenant subdomain gets its own site block that reverse proxies to that tenant's Rocket.Chat host port. Site blocks are generated from the tenancy table by a small render script (single source of truth in the DB, not hand-edited Caddyfile).
### 1.2 Directory and config layout
```text
/opt/wall-o/ # app code and compose, NOT /root
/opt/scirium/ # app code and compose, NOT /root
├── orchestrator/
│ ├── app/
│ │ ├── main.py # FastAPI app + routers
@@ -58,7 +58,7 @@ Caddy is the TLS edge. Each tenant subdomain gets its own site block that revers
└── run-backups.sh # mongodump + pg_dump to Wasabi S3
```
Web-served static assets (branding, PWA shell, custom CSS) live under /var/www/wall-o/ and are mounted read-only into each Rocket.Chat container. All files under /var/www/wall-o/ are chmod 644, owned by a service account, never by root home.
Web-served static assets (branding, PWA shell, custom CSS) live under /var/www/scirium/ and are mounted read-only into each Rocket.Chat container. All files under /var/www/scirium/ are chmod 644, owned by a service account, never by root home.
### 1.3 Tenant Docker Compose (Rocket.Chat + MongoDB)
@@ -77,7 +77,7 @@ services:
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:7.4.0 # pinned; dev CE for Phase 0
environment:
ROOT_URL: ${ROOT_URL} # https://wall-orthodontics.wall-o.itpropartner.com
ROOT_URL: ${ROOT_URL} # https://wall-orthodontics.scirium.itpropartner.com
MONGO_URL: mongodb://mongo:27017/rocketchat?replicaSet=rs0
MONGO_OPLOG_URL: mongodb://mongo:27017/local?replicaSet=rs0
PORT: "3000"
@@ -90,7 +90,7 @@ services:
ports:
- "127.0.0.1:30101:3000"
volumes:
- /var/www/wall-o/wall-orthodontics/branding:/app/branding:ro # chmod 644
- /var/www/scirium/wall-orthodontics/branding:/app/branding:ro # chmod 644
restart: unless-stopped
volumes:
@@ -153,15 +153,15 @@ Facts that drive the decision:
Decision: for a product we resell, use the FOSS-only build via the fossify script. MIT covers modification and commercial redistribution. The EE license restricts use and distribution, so shipping the stock image (which contains EE code) into a resold, white-labeled product is a licensing risk even if we never activate an EE key. We do not need EE features anyway: Rocket.Chat is chat transport only, and agents, retrieval, kb_scope, and the LLM all live in the orchestrator.
Consequence: maintain a private fork plus a CI job that runs fossify and builds a FOSS image (wall-o/rocketchat:foss). This is a Phase 1 gate, not a Phase 0 requirement. Phase 0 uses the stock CE image for speed, explicitly dev-only and never resold. No customer deployment ships before the FOSS image build is in CI.
Consequence: maintain a private fork plus a CI job that runs fossify and builds a FOSS image (scirium/rocketchat:foss). This is a Phase 1 gate, not a Phase 0 requirement. Phase 0 uses the stock CE image for speed, explicitly dev-only and never resold. No customer deployment ships before the FOSS image build is in CI.
### 2.2 Server rebrand steps (concrete)
Because we control the FOSS source, branding is a code patch plus admin settings, not a fragile CSS-only overlay.
1. Fork Rocket.Chat and run ./fossify.sh; build wall-o/rocketchat:foss.
2. Patch the footer and login strings in the fork: replace "Powered by Rocket.Chat" and the Rocket.Chat wordmark references with the Wall-O mark, and default the site name.
3. Replace bundled logo and favicon assets with per-tenant assets served from /var/www/wall-o/<tenant>/branding/ (chmod 644), mounted read-only into the container.
1. Fork Rocket.Chat and run ./fossify.sh; build scirium/rocketchat:foss.
2. Patch the footer and login strings in the fork: replace "Powered by Rocket.Chat" and the Rocket.Chat wordmark references with the Scirium mark, and default the site name.
3. Replace bundled logo and favicon assets with per-tenant assets served from /var/www/scirium/<tenant>/branding/ (chmod 644), mounted read-only into the container.
4. In the workspace admin (Settings, Layout): set Site Name, Site URL, language, and default roles; set the custom color scheme via Custom CSS.
5. Disable telemetry, the workspace registration prompt, and the "Register" gate in the fork for self-hosted tenants.
6. Bake default colors, logo, and favicon into the image; override per tenant via mounted branding assets and admin settings.
@@ -186,23 +186,23 @@ Goal: prove the core loop end to end: Rocket.Chat up, bot registered, channel cr
Phase 0 uses the stock CE image for speed (dev-only). The FOSS image build from section 2.1 is a Phase 1 gate before any customer.
- [ ] 1. Provision host and install Docker. `apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin`
- [ ] 2. Create service account and directories. `useradd -r -s /usr/sbin/nologin wallo && mkdir -p /opt/wall-o/tenants/wall-orthodontics /var/www/wall-o/wall-orthodontics/branding`
- [ ] 2. Create service account and directories. `useradd -r -s /usr/sbin/nologin scirium && mkdir -p /opt/scirium/tenants/wall-orthodontics /var/www/scirium/wall-orthodontics/branding`
- [ ] 3. Write tenant compose and mongod.conf (section 1.3). Populate .env from Vaultwarden. No secrets inline.
- [ ] 4. Start the stack. `docker compose -f /opt/wall-o/tenants/wall-orthodontics/docker-compose.yml up -d`
- [ ] 5. Initialize the Mongo replica set (oplog). `docker compose -f /opt/wall-o/tenants/wall-orthodontics/docker-compose.yml exec mongo mongosh -eval "rs.initiate()"`
- [ ] 6. Verify workspace is reachable. `curl -sI https://wall-orthodontics.wall-o.itpropartner.com` returns 200 after Caddy cert issuance.
- [ ] 7. Login as admin and capture admin identity. `curl -s https://wall-orthodontics.wall-o.itpropartner.com/api/v1/login -H "Content-Type: application/json" -d '{"user":"admin","password":"<from Vaultwarden>"}'`
- [ ] 8. Register the agent bot user. `curl -s .../api/v1/users.create -H "X-Auth-Token: <adminToken>" -H "X-User-Id: <adminUserId>" -d '{"name":"Wall-O Agent","username":"wallo.agent","email":"wallo-agent@wall-orthodontics.internal","password":"<from Vaultwarden>","roles":["bot"],"joinDefaultChannels":false,"verified":true}'`
- [ ] 4. Start the stack. `docker compose -f /opt/scirium/tenants/wall-orthodontics/docker-compose.yml up -d`
- [ ] 5. Initialize the Mongo replica set (oplog). `docker compose -f /opt/scirium/tenants/wall-orthodontics/docker-compose.yml exec mongo mongosh -eval "rs.initiate()"`
- [ ] 6. Verify workspace is reachable. `curl -sI https://wall-orthodontics.scirium.itpropartner.com` returns 200 after Caddy cert issuance.
- [ ] 7. Login as admin and capture admin identity. `curl -s https://wall-orthodontics.scirium.itpropartner.com/api/v1/login -H "Content-Type: application/json" -d '{"user":"admin","password":"<from Vaultwarden>"}'`
- [ ] 8. Register the agent bot user. `curl -s .../api/v1/users.create -H "X-Auth-Token: <adminToken>" -H "X-User-Id: <adminUserId>" -d '{"name":"Scirium Agent","username":"scirium.agent","email":"scirium-agent@wall-orthodontics.internal","password":"<from Vaultwarden>","roles":["bot"],"joinDefaultChannels":false,"verified":true}'`
- [ ] 9. Create a personal access token for the bot. `curl -s .../api/v1/users.createToken -H "X-Auth-Token: <adminToken>" -H "X-User-Id: <adminUserId>" -d '{"userId":"<botUserId>"}'`; store botUserId plus botAuthToken in Vaultwarden.
- [ ] 10. Create the knowledge channel. `curl -s .../api/v1/channels.create -H "X-Auth-Token: <adminToken>" -H "X-User-Id: <adminUserId>" -d '{"name":"employee-resources"}'`
- [ ] 11. Attach the agent to the channel. `curl -s .../api/v1/channels.addOwner -H "X-Auth-Token: <adminToken>" -H "X-User-Id: <adminUserId>" -d '{"roomId":"<roomId>","userId":"<botUserId>"}'`
- [ ] 12. Confirm the bot can post. `curl -s .../api/v1/chat.postMessage -H "X-Auth-Token: <botAuthToken>" -H "X-User-Id: <botUserId>" -d '{"roomId":"<roomId>","text":"Wall-O agent online."}'`
- [ ] 13. Stand up the orchestrator skeleton plus Postgres + pgvector. `docker compose -f /opt/wall-o/orchestrator/docker-compose.yml up -d` with image pgvector/pgvector:pg16, port 127.0.0.1:5432, credentials from .env (Vaultwarden).
- [ ] 12. Confirm the bot can post. `curl -s .../api/v1/chat.postMessage -H "X-Auth-Token: <botAuthToken>" -H "X-User-Id: <botUserId>" -d '{"roomId":"<roomId>","text":"Scirium agent online."}'`
- [ ] 13. Stand up the orchestrator skeleton plus Postgres + pgvector. `docker compose -f /opt/scirium/orchestrator/docker-compose.yml up -d` with image pgvector/pgvector:pg16, port 127.0.0.1:5432, credentials from .env (Vaultwarden).
- [ ] 14. Run migrations to create tenants, channels, agents, kb_scope, documents, chunks tables (section 4.2 columns).
- [ ] 15. Seed the tenants row with rocket_chat_url, rocket_chat_admin_user_id, and rocket_chat_admin_token_ref for Wall Orthodontics, and the agents row with the bot user id and bot token reference; leave all tokens in Vaultwarden only.
- [ ] 16. Upload a test document. `curl -s -F "file=@staff-handbook.pdf" -F "tenant_id=<tenantId>" -F "channel_id=<channelId>" https://api.wall-o.itpropartner.com/v1/documents`; orchestrator stores the file and records kb_scope.
- [ ] 16. Upload a test document. `curl -s -F "file=@staff-handbook.pdf" -F "tenant_id=<tenantId>" -F "channel_id=<channelId>" https://api.scirium.itpropartner.com/v1/documents`; orchestrator stores the file and records kb_scope.
- [ ] 17. Index the document. Orchestrator chunks, embeds via admin-ai, and inserts vectors into pgvector with tenant_id plus channel_id on every row.
- [ ] 18. Retrieval smoke test. `curl -s "https://api.wall-o.itpropartner.com/v1/retrieve?tenant_id=<tenantId>&channel_id=<channelId>&q=<question>"` returns a scoped chunk.
- [ ] 18. Retrieval smoke test. `curl -s "https://api.scirium.itpropartner.com/v1/retrieve?tenant_id=<tenantId>&channel_id=<channelId>&q=<question>"` returns a scoped chunk.
- [ ] 19. Close the chat loop. Orchestrator polls the channel via `channels.messages?roomId=<roomId>` and replies through chat.postMessage using the bot identity; verify a staff question gets a grounded answer.
- [ ] 20. Verify mobile. Open the tenant subdomain in a mobile browser (install the PWA) and confirm chat renders and the bot replies.
- [ ] 21. Verify push. Configure Push settings in the workspace (gateway URL), send a direct message to a test user on a mobile device, confirm the notification arrives on the PWA or the Rocket.Chat mobile app pointed at the server.
@@ -228,7 +228,7 @@ All components are self-hosted on netcup infrastructure in the chosen region. Ch
### 4.4 Backups
Nightly job in /opt/wall-o/backups/run-backups.sh: per-tenant mongodump (via the loopback port) plus orchestrator pg_dump, encrypted, uploaded to Wasabi S3. Retention per the ITPP backup schedule with a documented RPO. Backups are restorable per tenant, matching the isolation boundary.
Nightly job in /opt/scirium/backups/run-backups.sh: per-tenant mongodump (via the loopback port) plus orchestrator pg_dump, encrypted, uploaded to Wasabi S3. Retention per the ITPP backup schedule with a documented RPO. Backups are restorable per tenant, matching the isolation boundary.
### 4.5 Secret management