diff --git a/content/docs/configure/localization.mdx b/content/docs/configure/localization.mdx new file mode 100644 index 0000000..a851c10 --- /dev/null +++ b/content/docs/configure/localization.mdx @@ -0,0 +1,68 @@ +--- +title: Localization +description: Set the tenant-wide timezone, language, country, and date, time, and number formats that every rendered value inherits. +--- + +# Localization + +Localization sets the **tenant-level defaults** for how ObjectOS interprets +time, chooses a message catalog, and renders dates, numbers, and currency. +These values are the fallback for the whole workspace — individual users can +override their own language in their [Account](/docs/use/profile), but the +defaults you set here apply to everyone who has not. + +Open **Setup → Configuration → Localization**. The page is split into two +sections: **Region** and **Formats**. + +## Region + +Region controls how ObjectOS resolves *meaning* — which timezone anchors +relative-time calculations, which locale drives formatting, and which country +the deployment reports as its home. + +| Setting | Default | Drives | +|---|---|---| +| `Default timezone` | `UTC` | IANA zone for `today()` / `daysFromNow`, analytics date buckets, and rendered datetimes | +| `Default language` | `English (US)` | BCP-47 locale for message catalogs and number/date formatting | +| `Default country` | `US` | ISO 3166-1 alpha-2 code (e.g. `US`, `GB`, `CN`) | + +> **Timezone is not cosmetic.** It is the anchor for every relative-time +> expression and for the buckets analytics rolls records into. Changing it +> shifts what "today" means across the tenant — set it once, deliberately. + +`Default timezone` is a dropdown of IANA zones (`UTC`, `America/New_York`, +`Asia/Shanghai`, and so on). `Default language` selects the locale whose +message catalog and formatting rules the UI falls back to. `Default country` +is a free-text field that expects a two-letter ISO code. + +## Formats + +Formats control *presentation* — how an already-resolved value is written out. +They do not change stored data, only how it is displayed. + +| Setting | Default | Example | +|---|---|---| +| `Date format` | ISO | `2026-06-17` | +| `Time format` | 24-hour | `14:30` | +| `Number format` | comma / dot | `1,234.56` | +| `Currency` | — | Currency symbol and placement for money fields | + +Each is a dropdown. Pick the presentation your users expect; the underlying +timestamps and numbers are stored in a canonical form and only formatted at +render time. + +## Tenant defaults vs. user overrides + +Everything on this page is a **tenant default**. When a user sets their own +language in **Account**, that choice wins for that user's session and rendered +UI; users who leave their preference unset inherit the `Default language` you +configure here. Timezone, country, and format defaults apply tenant-wide. + +## Where to go next + +| Task | Page | +|---|---| +| Change branding, feature flags, and other tenant settings | [System Settings](/docs/configure/system-settings) | +| Configure a user's personal language override | [Your profile](/docs/use/profile) | +| Set up transactional email delivery | [Email](/docs/configure/email) | +| Return to the administration overview | [Configure](/docs/configure) | diff --git a/content/docs/configure/meta.de.json b/content/docs/configure/meta.de.json index 7d0adda..7d4df5e 100644 --- a/content/docs/configure/meta.de.json +++ b/content/docs/configure/meta.de.json @@ -1,5 +1,5 @@ { "title": "Konfigurieren", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.es.json b/content/docs/configure/meta.es.json index a44bc2a..6f8f11b 100644 --- a/content/docs/configure/meta.es.json +++ b/content/docs/configure/meta.es.json @@ -1,5 +1,5 @@ { "title": "Configurar", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.fr.json b/content/docs/configure/meta.fr.json index 97c61f8..c1a78cf 100644 --- a/content/docs/configure/meta.fr.json +++ b/content/docs/configure/meta.fr.json @@ -1,5 +1,5 @@ { "title": "Configurer", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.ja.json b/content/docs/configure/meta.ja.json index 4e1e8df..5cd8f79 100644 --- a/content/docs/configure/meta.ja.json +++ b/content/docs/configure/meta.ja.json @@ -1,5 +1,5 @@ { "title": "設定", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.json b/content/docs/configure/meta.json index 2315db4..82c5df2 100644 --- a/content/docs/configure/meta.json +++ b/content/docs/configure/meta.json @@ -1,5 +1,5 @@ { "title": "Configure", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.ko.json b/content/docs/configure/meta.ko.json index e241b9a..79d776a 100644 --- a/content/docs/configure/meta.ko.json +++ b/content/docs/configure/meta.ko.json @@ -1,5 +1,5 @@ { "title": "설정", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/meta.zh-Hans.json b/content/docs/configure/meta.zh-Hans.json index c922ce4..3102417 100644 --- a/content/docs/configure/meta.zh-Hans.json +++ b/content/docs/configure/meta.zh-Hans.json @@ -1,5 +1,5 @@ { "title": "配置", "defaultOpen": false, - "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "api-access", "webhooks", "email"] + "pages": ["index", "users", "runtime", "data-sources", "authentication", "permissions", "storage", "ai", "mcp", "system-settings", "localization", "notifications", "api-access", "webhooks", "email"] } diff --git a/content/docs/configure/notifications.mdx b/content/docs/configure/notifications.mdx new file mode 100644 index 0000000..2a7b0b8 --- /dev/null +++ b/content/docs/configure/notifications.mdx @@ -0,0 +1,120 @@ +--- +title: Notifications +description: Configure how ObjectOS routes events into user inboxes — subscriptions, per-user preferences, and render templates. +--- + +# Notifications + +This page covers the **administrator side** of notifications: how events become +messages, and the three system-managed objects you use to route and render +them. For the recipient's view of the inbox — reading and muting notifications — +see [Notifications](/docs/use/notifications) under *Use*. + +## The notification pipeline + +A notification is not a single record. It flows through four stages: + +```text +emit() → Notification Event → routed by Subscription + Preference + Template → Inbox Message +``` + +1. **`emit()`** — Application code raises an event (an approval submitted, a + record shared, an invitation sent). +2. **Notification Event** (`sys_notification`) — Each `emit()` writes one + ingress row. This is the diagnostic log of *what happened*, before any + delivery decision. See [Audit Logs](/docs/operate/audit-logs) for how to + read it. +3. **Routing** — For each event, ObjectOS resolves who should be notified + (**Subscriptions**), whether each recipient allows that topic on that channel + (**Preferences**), and how the message should be rendered (**Templates**). +4. **Inbox Message** (`sys_inbox_message`) — The materialized, per-user result + the recipient actually sees in their inbox. + +Preferences, Subscriptions, and Templates are the admin/system-side +configuration. Inbox Messages are the user-side output. + +### How routing resolves + +For a single event, the three objects each answer one question: + +| Object | Question it answers | +|---|---| +| Notification Subscription | *Who is interested?* — which principals stand subscribed to the topic | +| Notification Preference | *Does this recipient allow it here?* — the per-user mute/allow for the topic and channel | +| Notification Template | *How is it written?* — the subject and body to render for the recipient's channel and locale | + +Only when a recipient is subscribed **and** their preference for the +topic/channel is enabled does a template render and an inbox message +materialize. All three objects are seeded and maintained by the platform, so +the list views mostly show system-generated rows. + +## Notification Preferences + +At **Setup → Configuration → Notification Preferences** (`sys_notification_preference`). + +Per-user × topic × channel toggle (mute/allow), with admin-global defaults. A +preference decides whether a given recipient receives a given topic on a given +channel. + +| Field | Purpose | +|---|---| +| `user_id` | The principal the preference belongs to | +| `topic` | Notification topic (e.g. `project.digest`) | +| `channel` | Delivery channel (in-app, email, …) | +| `enabled` | Boolean — allow or mute this topic/channel for the user | +| `digest` | Batching cadence for the topic | +| `quiet_hours` | JSON window during which delivery is suppressed | +| `created_at` / `updated_at` | Audit timestamps | + +> Entries appear automatically when their source action first runs (for +> example *Submit for Approval*, *Share*, or *Invite*) — you rarely create +> preference rows by hand. Use the list to adjust admin defaults or mute a +> noisy topic. + +## Notification Subscriptions + +At **Setup → Configuration → Notification Subscriptions** (`sys_notification_subscription`). + +A **standing subscription** of a principal (role, team, or user) to a +notification topic. Subscriptions answer *who is interested* in a topic before +per-user preferences filter delivery. + +| Field | Purpose | +|---|---| +| `topic` | The topic being subscribed to | +| `principal` | Role, team, or user that receives the topic | +| `enabled` | Boolean — activate or pause the subscription | + +## Notification Templates + +At **Setup → Configuration → Notification Templates** (`sys_notification_template`). + +A per **(topic × channel × locale)** render template. Templates turn an event +payload into the subject and body a recipient reads, in their locale and for +their channel. + +| Field | Purpose | +|---|---| +| `topic` | Topic this template renders | +| `channel` | Channel the rendered output targets | +| `locale` | Locale of this rendering (matched to the recipient) | +| `version` | Template version number | +| `subject` | Rendered title | +| `body` | Message body (markdown) | +| `format` | Output format for the body | +| `is_active` | Boolean — whether this template is used for rendering | + +These objects are **system-managed**: rows are seeded by the platform and the +capabilities you run, so most of your work is editing template content or +toggling `is_active`, `enabled`, and preference defaults rather than creating +records from scratch. + +## Where to go next + +| Task | Page | +|---|---| +| Configure the email channel used for delivery | [Email](/docs/configure/email) | +| Diagnose events with the ingress log and audit trail | [Audit Logs](/docs/operate/audit-logs) | +| See the recipient's inbox experience | [Notifications](/docs/use/notifications) | +| Set locale defaults that templates match against | [Localization](/docs/configure/localization) | +| Return to the administration overview | [Configure](/docs/configure) | diff --git a/content/docs/configure/system-settings.mdx b/content/docs/configure/system-settings.mdx index 4259c9a..1219325 100644 --- a/content/docs/configure/system-settings.mdx +++ b/content/docs/configure/system-settings.mdx @@ -56,6 +56,31 @@ Customer-facing settings usually include: | AI providers | Model provider, API key, budget limits | | SSO | OIDC provider settings and test connection | +## Branding + +At **Setup → Configuration → Branding**. These settings control the workspace's +display identity — its name, logo, and colours. + +| Setting | Notes | +|---|---| +| `Workspace name` | Required. The name shown across the UI (default `ObjectStack`) | +| `Support email` | Address surfaced to users for help (e.g. `support@example.com`) | +| `Default theme` | `Match system`, `light`, or `dark` | +| `Accent colour` | Hex colour with a picker (default `#6366f1`) | +| `Logo URL` | URL of the workspace logo | + +## Feature flags + +At **Setup → Configuration → Feature Flags** `[Beta]`. Toggle experimental and +beta features for this workspace — grouped as **Productivity** (AI Assistant, +Kanban swimlanes) and **Collaboration** (Realtime cursors, Inline comments). +Each is a tenant-level UI switch. + +> **Beta features may change without notice.** Pin a flag with an environment +> variable (e.g. `OS_FEATURE_FLAGS_AI_ENABLED=true`) to lock it for the whole +> deployment. Because environment overrides are locked, the `OS_FEATURE_FLAGS_*` +> vars take precedence over the UI toggles. + ## Secrets Password and credential fields should be encrypted by the settings diff --git a/content/docs/operate/audit-logs.mdx b/content/docs/operate/audit-logs.mdx new file mode 100644 index 0000000..a8e940d --- /dev/null +++ b/content/docs/operate/audit-logs.mdx @@ -0,0 +1,126 @@ +--- +title: Audit Logs +description: Read the immutable audit trail and diagnostics logs that record every change, sign-in, and emitted event on your deployment. +--- + +# Audit Logs + +The audit log is the immutable record of what happened on your deployment: who +changed what, when, and from where. This page is the deep reference for the +diagnostics surfaces under **Setup → Diagnostics**. For the operator overview of +logs, metrics, and request identity, see +[Observability](/docs/operate/observability). + +> These surfaces require the `manage_platform_settings` permission. + +Reach for the audit log when you need to prove or investigate: + +- permission-sensitive changes; +- settings and configuration changes; +- user and session activity; +- integration and automation activity; +- denied-access analysis. + +## Audit Logs + +At **Setup → Diagnostics → Audit Logs** (`sys_audit_log`). The object is +**read-only and immutable** — an append-only trail of platform events. You can +filter, group, and inspect rows, but nothing can edit or delete them from the +Console. + +### Preset views + +The list opens with tabs that filter by action category: + +| View | Shows | +|---|---| +| `Recent` | All events, newest first | +| `Writes` | Create / update / delete actions | +| `Auth` | Sign-in, sign-out, and authentication events | +| `Config` | Settings and configuration changes | + +### Columns and fields + +The default columns are `Timestamp`, `Action` (a coloured pill — +create / update / …), `Object`, `Record ID`, and `Actor`. The footer shows the +total record count (e.g. *36 records*). + +Each row carries the full field set: + +| Field | Meaning | +|---|---| +| `created_at` | When the event was recorded | +| `action` | The operation (create, update, delete, auth, …) | +| `user_id` | Lookup to the acting User | +| `actor` | Textual actor identity | +| `object_name` | The object the event touched (e.g. `sys_user`) | +| `record_id` | The affected record | +| `old_value` | Prior value (textarea) | +| `new_value` | New value (textarea) | +| `ip_address` | Source IP of the request | +| `user_agent` | Client user agent | +| `tenant_id` | Owning tenant | +| `metadata` | Additional structured context | + +> The `Config` view is the fastest way to answer "who changed this setting?" — +> it narrows the trail to configuration actions before you start reading rows. + +### Reading a change + +For write actions, the interesting detail is the before/after. Open a row's +`⋮` menu to expand `old_value` and `new_value` and see exactly what changed on +that record. The `Object` and `Record ID` columns tell you *what* was touched; +`old_value`/`new_value` tell you *how*; `actor`, `ip_address`, and `user_agent` +tell you *who* and *from where*. + +> For regulated environments, back the immutability up at the storage layer — +> make the table append-only at the database and define a retention policy. + +## Notification Events + +At **Setup → Diagnostics → Notification Events** (`sys_notification`). This is +the **ingress log of the notification system** — one row per `emit()`, written +before any delivery decision. Use it to diagnose why a notification did or did +not reach an inbox; the routing and materialization that follow are documented +in [Notifications](/docs/configure/notifications). + +Preset views are `Recent` and `By Topic`. Default columns: `Topic` (e.g. +`project.digest`), `Severity` (an info/warn/… pill), `Actor`, `Source Object`, +and `Created At`. + +| Field | Meaning | +|---|---| +| `topic` | The emitted topic | +| `payload` | Event payload (JSON) | +| `severity` | Severity level | +| `dedup_key` | Key used to collapse duplicate emits | +| `source_object` | Object that raised the event | +| `source_id` | Record that raised the event | +| `actor_id` | Principal that triggered the emit | +| `created_at` | When the event was ingested | + +The `dedup_key` collapses duplicate emits, and `payload` carries the raw event +context that templates render from. Because this log sits *upstream* of routing, +a row here with no matching inbox message usually means a subscription or +preference filtered the event out — check +[Notifications](/docs/configure/notifications) when a user reports a missing +alert. + +Downstream, each event is materialized into per-user inbox messages +(`sys_inbox_message`) — the recipient's view lives under +[Notifications](/docs/use/notifications). + +## Sessions + +At **Setup → Diagnostics → Sessions**. Sessions lists active and recent +sign-in sessions, so you can investigate a user's activity or revoke access. +Pair it with the `Auth` audit view when reviewing a sign-in incident. + +## Where to go next + +| Task | Page | +|---|---| +| Operator overview of logs, metrics, and request identity | [Observability](/docs/operate/observability) | +| Understand how notifications are routed and rendered | [Notifications](/docs/configure/notifications) | +| Harden a deployment before go-live | [Production Readiness](/docs/operate/production) | +| Return to the operations overview | [Operate](/docs/operate) | diff --git a/content/docs/operate/index.mdx b/content/docs/operate/index.mdx new file mode 100644 index 0000000..172e94c --- /dev/null +++ b/content/docs/operate/index.mdx @@ -0,0 +1,38 @@ +--- +title: Operate +description: Keep a running ObjectOS deployment healthy — production readiness, observability, audit trails, backups, upgrades, and recovery. +--- + +# Operate + +This section is for keeping ObjectOS **healthy in production**. Where +[Configure](/docs/configure) covers setup-time administration — users, access, +sign-in, integrations — *Operate* covers the day-two work: hardening the +deployment, watching it, proving what happened, and recovering when something +goes wrong. + +## Operations pages + +| Page | Use it to | +|---|---| +| [Production Readiness](/docs/operate/production) | Harden a deployment before and after go-live | +| [Observability](/docs/operate/observability) | Wire up logs, request ids, metrics, and errors | +| [Audit Logs](/docs/operate/audit-logs) | Read the immutable audit trail and diagnostics logs | +| [Backup](/docs/operate/backup) | Plan backups and disaster recovery | +| [Upgrade](/docs/operate/upgrade) | Upgrade or roll back safely | +| [Troubleshooting](/docs/operate/troubleshooting) | Diagnose a broken deployment | + +## Configure vs. Operate + +Setup-time admin — adding users, granting access, wiring email, storage, and +integrations — lives under [Configure](/docs/configure). Come back here once the +deployment is live and you need to observe, audit, back up, or upgrade it. + +## Where to go next + +| Task | Page | +|---|---| +| Pre-production checklist | [Production Readiness](/docs/operate/production) | +| Trace a change or a sign-in | [Audit Logs](/docs/operate/audit-logs) | +| Set up monitoring | [Observability](/docs/operate/observability) | +| Setup-time administration | [Configure](/docs/configure) | diff --git a/content/docs/operate/meta.de.json b/content/docs/operate/meta.de.json index b34df3d..ec4218e 100644 --- a/content/docs/operate/meta.de.json +++ b/content/docs/operate/meta.de.json @@ -2,8 +2,10 @@ "title": "Betrieb", "defaultOpen": false, "pages": [ + "index", "production", "observability", + "audit-logs", "backup", "upgrade", "troubleshooting" diff --git a/content/docs/operate/meta.es.json b/content/docs/operate/meta.es.json index d06fd7f..5039abe 100644 --- a/content/docs/operate/meta.es.json +++ b/content/docs/operate/meta.es.json @@ -2,8 +2,10 @@ "title": "Operar", "defaultOpen": false, "pages": [ + "index", "production", "observability", + "audit-logs", "backup", "upgrade", "troubleshooting" diff --git a/content/docs/operate/meta.fr.json b/content/docs/operate/meta.fr.json index 9fb6b1b..6cce14d 100644 --- a/content/docs/operate/meta.fr.json +++ b/content/docs/operate/meta.fr.json @@ -2,8 +2,10 @@ "title": "Exploitation", "defaultOpen": false, "pages": [ + "index", "production", "observability", + "audit-logs", "backup", "upgrade", "troubleshooting" diff --git a/content/docs/operate/meta.ja.json b/content/docs/operate/meta.ja.json index aac8652..9527ee8 100644 --- a/content/docs/operate/meta.ja.json +++ b/content/docs/operate/meta.ja.json @@ -2,8 +2,10 @@ "title": "運用", "defaultOpen": false, "pages": [ + "index", "production", "observability", + "audit-logs", "backup", "upgrade", "troubleshooting" diff --git a/content/docs/operate/meta.json b/content/docs/operate/meta.json index d1d9324..68a7bf6 100644 --- a/content/docs/operate/meta.json +++ b/content/docs/operate/meta.json @@ -1,5 +1,5 @@ { "title": "Operate", "defaultOpen": false, - "pages": ["production", "observability", "backup", "upgrade", "troubleshooting"] + "pages": ["index", "production", "observability", "audit-logs", "backup", "upgrade", "troubleshooting"] } diff --git a/content/docs/operate/meta.ko.json b/content/docs/operate/meta.ko.json index 400477f..3d56e31 100644 --- a/content/docs/operate/meta.ko.json +++ b/content/docs/operate/meta.ko.json @@ -2,8 +2,10 @@ "title": "운영", "defaultOpen": false, "pages": [ + "index", "production", "observability", + "audit-logs", "backup", "upgrade", "troubleshooting" diff --git a/content/docs/operate/meta.zh-Hans.json b/content/docs/operate/meta.zh-Hans.json index 7f34359..6697c53 100644 --- a/content/docs/operate/meta.zh-Hans.json +++ b/content/docs/operate/meta.zh-Hans.json @@ -1,5 +1,5 @@ { "title": "运维", "defaultOpen": false, - "pages": ["production", "observability", "backup", "upgrade", "troubleshooting"] + "pages": ["index", "production", "observability", "audit-logs", "backup", "upgrade", "troubleshooting"] } diff --git a/content/docs/operate/observability.mdx b/content/docs/operate/observability.mdx index d517a83..5c26ec5 100644 --- a/content/docs/operate/observability.mdx +++ b/content/docs/operate/observability.mdx @@ -107,6 +107,9 @@ Use audit logs for: For regulated environments, make the audit table append-only at the database or storage layer and define a retention policy. +For the full field reference, preset views, and the sibling diagnostics logs, +see [Audit Logs](/docs/operate/audit-logs). + ## Console diagnostics The Console exposes operational surfaces such as: