Rosie — architecture, security, operation
The technical reference for IT service providers and IT contacts at the customer. Swiss instance, security headers, app cache, web push, database migrations, backup, observability and escalation — all traceable. Provider names appear here deliberately, because you have to open firewall rules and document the outsourcing.
System architecture
Rosie is a vanilla-JavaScript progressive web app. The application runs as a Node process on a Debian instance at Infomaniak in Switzerland, fronted by Caddy as a reverse proxy with automatic certificate management. Persistence uses libSQL/SQLite on the same instance (WAL mode), object storage via the S3-compatible object store at Infomaniak. The service worker uses a CACHE_PREFIX per release. A protective service sits in front of the public website — it holds no data; the API talks directly to the Swiss instance.
Browser compatibility
DNS and domains
- Main domain:
rosie-app.ch(includingwww). - Alias / mirror:
rosie-planer.com— as a 301 redirect. Expect a cache window of about two minutes that resolves on its own. To check the origin immediately, use?cb=<random>. - App subdomain: the application runs under its own name pointing directly at the Swiss instance (“DNS only”, with no intermediary service).
- No wildcard record.
*.rosie-app.chdoes not exist — an invented name does not resolve. That is deliberate and rules out subdomain takeover. - The protective service in front covers the public website only; it holds no customer data.
rosie-planer.com may briefly come from the cache of the service in front. It resolves on its own. For forensics: an origin request with a cache buster.Security headers
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload — set by the application itself, so the header applies regardless of the service in front. Submission to hstspreload.org is done manually.WORKER_VERSION = RELEASE, imported from shared/version.mjs (a single source).curl -I https://rosie-app.ch shows every header that is set, including HSTS, CSP, X-Worker-Version and X-Request-Id.includeSubDomains applies to every subdomain, including test and staging names. And once delivered, an HSTS header stays valid in the browser for up to two years — it cannot be withdrawn at short notice.Service worker, asset cache
sw.jswith CACHE_PREFIX, stamped fromshared/version.mjs(scripts/sync-version.mjs).- Upstream cache: about two minutes of lag after a deployment, which resolves on its own.
immutablecache header for versioned assets.- Lazily loaded libraries via
_loadVendor— XLSX, html2canvas. - iOS splash screens must be PNG — WebP dropped in release r168.
- No background sync — deliberately: a replay without an open tab would have no fresh token and, without idempotency keys, would risk duplicate writes. The chat outbox only flushes while the app is open (see
docs/OFFLINE.md). - Web push on iOS works only in the installed app — enforce adding it to the home screen.
RELEASE in shared/version.mjs then npm run version:sync — CACHE_PREFIX in sw.js / src/constants.js are stamped automatically; nothing needs updating by hand.Web push (RFC 8291)
- VAPID keys (public and private) are stored as secrets on the instance under
/etc/rosie/env. subscribeToPushNotificationsis an idempotent upsert.- Quiet hours are respected.
- On or off per alert category:
bounty·planPublished·adminAlert·messages·absenceResult.
Firewall / network
- Outbound HTTPS on port 443 only.
- Allow for
rosie-app.chand the app subdomain. No other destinations are needed — the app does not call any service at the customer on its own. - No inbound ports.
- No WebSocket required — the app polls every 60 seconds.
Email system
Delivery via SMTP to a Swiss mailbox at Hostpoint. The sender of all system email is support@rosie-app.ch — an address you can reply to, not a no-reply dead end. SPF, DKIM and DMARC are configured; we recommend testing delivery against the customer’s spam filter once after initial setup.
rosie-app.ch . Adding support@rosie-app.ch to the allow list resolves most cases.Mobile & MDM
- iOS 14.5+, Android 8.0+.
- A web app — no app store package.
- MDM can configure the preferred browser, home screen web clips and trusted sites .
- Note: Web push on iOS requires the installed app; iOS splash screen in PNG (not WebP).
Database migrations and schema versions
Migrations live under database/migrations/ , numbered consecutively, and are applied forward only. The current state is in the directory itself — this page deliberately names no number, since it would be wrong by the next release. Every run is followed by a schema check. The migrations are built so that an empty database can be rebuilt entirely from them.
Backup & Recovery
- Automatic backups of the database, encrypted and stored off site.
- A 30-day recovery window with hourly recovery points (RPO of one hour or less).
- Object storage is backed up separately.
- A full data export per tenant, at any time from the administration interface.
- No geographic redundancy. One production instance is run deliberately — a restart or an update means a short outage. That is a known and accepted trade-off, and it can be added later without changing the architecture.
Rollback / versions
Every release has a tag checkpoint-rNNN-deployed in the source control system, so it can always be shown which version was live and when.
curl -I → X-Worker-Version to check.Tenant isolation
- Server-side tenant scoping —
tenant_idin every query. - The in-memory tenant globals are cleared on sign-out via
_resetTenantCalendarData()(six calendar globals). - Cross-tenant leak tests are pinned by regression cases.
- Persistence is triggered by a tenant marker
companySettingsDirty.
Observability & Logs
- X-Worker-Version (r166 A10), X-Request-Id in every response.
- Web Vitals →
/api/analytics, sent with keepalive, Do Not Track respected. - A personal-data scrubber runs before analytics.
- k-anonymity of at least 4 for aggregate charts.
- Logs sit on the instance (systemd/journald) and are evaluated by the vendor; an external uptime monitor checks availability and raises alerts.
Performance budget
- LCP / CLS / INP targets as the performance budget.
- Layout-shift fix:
width/heighton<img>tags. - Lazily loaded libraries via
_loadVendor— XLSX / html2canvas. - Battery saving: polling pauses when
document.hidden(paused when hidden).
Key API endpoints
/api/staff · /api/shift-assignments · /api/vacations/api/absences · /api/absences/:id/{approve,reject,cancel} · /api/absence-approval-config/api/messages · /api/suggestions/api/qms/documents/api/tasks · /api/tasks/templates · /api/tasks/:id/qms-links (PATCH) · /api/tasks/audit/api/mutations · /api/onboarding/:step/api/analytics · /api/log/api/profile/r163-monatsabschluss · /r163-monatsabschluss/:year_month (POST / DELETE)/api/feed-proxyX-Worker-Version) and a request id (X-Request-Id).AI system & Data-protection firewall
- AI provider: enabled per tenant; one fixed service per purpose, with no automatic fallback. Which provider is used is stated in the sub-processor list of the data processing agreement — not here, so that this page does not become wrong when the provider changes.
- Rate limit: 30 requests per hour per user.
- The personal-data sanitiser strips email addresses, social security numbers, IBANs, phone numbers and dates before every call to the AI service.
- Scheduled AI jobs
0 2/0 4for the task pattern learner — prompts withoutstaff.id. - Speech recognition: handled by the browser (Web Speech API); depending on the browser or operating system, the recording is sent to its own speech recognition service — ROSIE neither receives nor stores any audio recordings. For command recognition, only the recognized text goes to the AI service, with consent (Art. 6(6) revFADP).
Module system
Optional modules: Quality management (QMS), Voice-to-Schedule, Payroll preparation & finance, Smart Matchmaker, Workload radar, Regional network. Enabled per tenant under Administration → Tools.
Accessibility & Languages
- A global Escape key and focus trap .
- ARIA progress bar .
- Four interface languages: DE / FR / IT / EN.
- 14 chat languages for internal communication — the translation runs on the device.
Secrets management
- Secrets live in
/etc/rosie/envon the instance, readable only by the service account: the session signing key, the VAPID key pair, and credentials for object storage, SMTP and the AI service. - Rotate the signing key annually.
- Rotating the VAPID keys invalidates push subscriptions (a known limitation).
- Password hashing: PBKDF2-SHA-256 with a salt, in four chained rounds of 100,000 iterations each (400,000 in effect).
Initial setup for IT
A tenant is set up by the vendor on the Swiss instance. No installation is needed at the customer — no servers, no agents, no inbound ports. What follows is the list of items that genuinely sit on the customer side.
curl -I against the app address — headers including X-Worker-Version to check.support@rosie-app.ch to be allowed.Troubleshooting & Support
Procedures exist for: sign-in errors · database errors · deployment errors · email delivery · AI outage · push delivery · migration errors.
support@rosie-app.ch. Response times are governed by the service contract, not by this manual. For security reports, the disclosure channel is at /.well-known/security.txt.X-Request-Id and the time.Verifying data protection
- TLS 1.3.
- AES-256 at rest. Particularly sensitive free-text fields are additionally encrypted field by field.
- Data hosted in Switzerland (Infomaniak): compute, database, object storage and backups. The protective service in front of the public website and the payment provider are named in the sub-processor list of the data processing agreement.
- Data processing agreement in place.
- No cookies, no tracking — Do Not Track is respected.
- Key destruction as the operational revocation; erasure within 30 days of the end of the contract, with written evidence.
- SSO (SAML/OIDC) is not available and under evaluation; no committed date exists. Sign-in uses email and password, optionally with TOTP.
FAQ for IT
rosie-app.ch and the app subdomain is enough — calls to the AI service originate from the instance, not from the workstation.rosie-planer.com briefly out of date after a deployment?▶?cb=<random>).curl -I against the domain — the X-Worker-Version header gives the active release number, and X-Request-Id identifies the individual request for correlation in the server logs.Provider and processor: Digital Passion GmbH, Haldenstrasse 16, 4600 Olten, Switzerland · CHE-154.512.796
Questions? support@rosie-app.ch · rosie-app.ch
← Back to the overview