@objectstack/platform-objects 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -3266,6 +3266,20 @@ var defaultPermissionSets = [
3266
3266
  operation: "select",
3267
3267
  using: "id = current_user.id"
3268
3268
  },
3269
+ // Org collaborators: members can see other users in the same
3270
+ // organization. Without this, owner/assignee lookups, @-mention
3271
+ // suggestions, reviewer pickers and team-roster surfaces all
3272
+ // collapse to just the current user. `org_user_ids` is
3273
+ // pre-resolved by runtime/resolve-execution-context from
3274
+ // `sys_member` for the active organization. Sensitive credential
3275
+ // tables (`sys_account`, `sys_session`, `sys_api_key`, …) keep
3276
+ // their stricter self-only carve-outs above.
3277
+ {
3278
+ name: "sys_user_org_members",
3279
+ object: "sys_user",
3280
+ operation: "select",
3281
+ using: "id IN (current_user.org_user_ids)"
3282
+ },
3269
3283
  {
3270
3284
  name: "sys_session_self",
3271
3285
  object: "sys_session",
@@ -3363,8 +3377,14 @@ var defaultPermissionSets = [
3363
3377
  operation: "select",
3364
3378
  using: "id = current_user.id"
3365
3379
  },
3366
- // ── Per-user visibility on better-auth tables that lack
3367
- // `organization_id` (matches the `member_default` carve-outs).
3380
+ // Org collaborators (read-only): see `sys_user_org_members` in
3381
+ // `member_default` for rationale.
3382
+ {
3383
+ name: "sys_user_org_members",
3384
+ object: "sys_user",
3385
+ operation: "select",
3386
+ using: "id IN (current_user.org_user_ids)"
3387
+ },
3368
3388
  {
3369
3389
  name: "sys_session_self",
3370
3390
  object: "sys_session",
@@ -4091,13 +4111,56 @@ var SysNotification = ObjectSchema.create({
4091
4111
  displayNameField: "title",
4092
4112
  titleFormat: "{title}",
4093
4113
  compactLayout: ["title", "type", "is_read", "created_at"],
4114
+ /**
4115
+ * Row-level inbox actions. Use `visible` CEL expressions to ensure
4116
+ * `mark_read` only shows on unread rows and vice-versa, mirroring the
4117
+ * mark-as-read affordances in GitHub / Linear inboxes. The toolbar-level
4118
+ * `mark_all_read` is intentionally omitted server-side: it requires a
4119
+ * bulk update primitive that doesn't yet exist on the REST surface, and
4120
+ * the popover already handles the multi-row case client-side via N
4121
+ * single-row PATCHes (see `InboxPopover.tsx` -> AppHeader `markAllRead`).
4122
+ */
4123
+ actions: [
4124
+ {
4125
+ name: "mark_read",
4126
+ label: "Mark as Read",
4127
+ icon: "check",
4128
+ variant: "secondary",
4129
+ mode: "custom",
4130
+ locations: ["list_item"],
4131
+ type: "api",
4132
+ method: "PATCH",
4133
+ target: "/api/v1/data/sys_notification/{id}",
4134
+ bodyExtra: { is_read: true },
4135
+ visible: "!record.is_read",
4136
+ successMessage: "Notification marked as read",
4137
+ refreshAfter: true
4138
+ },
4139
+ {
4140
+ name: "mark_unread",
4141
+ label: "Mark as Unread",
4142
+ icon: "bell-dot",
4143
+ variant: "secondary",
4144
+ mode: "custom",
4145
+ locations: ["list_item"],
4146
+ type: "api",
4147
+ method: "PATCH",
4148
+ target: "/api/v1/data/sys_notification/{id}",
4149
+ bodyExtra: { is_read: false, read_at: null },
4150
+ visible: "record.is_read",
4151
+ successMessage: "Notification marked as unread",
4152
+ refreshAfter: true
4153
+ }
4154
+ ],
4094
4155
  listViews: {
4095
4156
  unread: {
4096
4157
  type: "grid",
4097
4158
  name: "unread",
4098
4159
  label: "Unread",
4099
4160
  data: { provider: "object", object: "sys_notification" },
4100
- columns: ["type", "title", "recipient_id", "created_at"],
4161
+ // Title + actor first (the "who/what" the user actually scans);
4162
+ // type stays as a categorising chip; created_at right-aligned.
4163
+ columns: ["title", "actor_name", "type", "created_at"],
4101
4164
  filter: [
4102
4165
  { field: "recipient_id", operator: "equals", value: "{current_user_id}" },
4103
4166
  { field: "is_read", operator: "equals", value: false }
@@ -4111,17 +4174,21 @@ var SysNotification = ObjectSchema.create({
4111
4174
  name: "mine",
4112
4175
  label: "Mine",
4113
4176
  data: { provider: "object", object: "sys_notification" },
4114
- columns: ["type", "title", "is_read", "created_at"],
4177
+ columns: ["title", "actor_name", "type", "is_read", "created_at"],
4115
4178
  filter: [{ field: "recipient_id", operator: "equals", value: "{current_user_id}" }],
4116
4179
  sort: [{ field: "created_at", order: "desc" }],
4117
- pagination: { pageSize: 50 }
4180
+ pagination: { pageSize: 50 },
4181
+ // Group by notification category so mention/assignment storms don't
4182
+ // hide system or task_due rows. Users still toggle to flat via the
4183
+ // toolbar Group control if they prefer chronology only.
4184
+ grouping: { fields: [{ field: "type", order: "asc", collapsed: false }] }
4118
4185
  },
4119
4186
  all_notifications: {
4120
4187
  type: "grid",
4121
4188
  name: "all_notifications",
4122
4189
  label: "All",
4123
4190
  data: { provider: "object", object: "sys_notification" },
4124
- columns: ["type", "title", "recipient_id", "is_read", "created_at"],
4191
+ columns: ["title", "recipient_id", "actor_name", "type", "is_read", "created_at"],
4125
4192
  sort: [{ field: "created_at", order: "desc" }],
4126
4193
  pagination: { pageSize: 100 }
4127
4194
  }
@@ -4974,6 +5041,14 @@ var SysApprovalRequest = ObjectSchema.create({
4974
5041
  description: "Record snapshot at submission time",
4975
5042
  group: "State"
4976
5043
  }),
5044
+ process_hash: Field.text({
5045
+ label: "Process Hash",
5046
+ required: false,
5047
+ maxLength: 80,
5048
+ readonly: true,
5049
+ description: "sha256 of the approval process body at submit time (ADR-0009 execution pinning). Resolved through sys_metadata_history so process upgrades do not affect in-flight requests.",
5050
+ group: "State"
5051
+ }),
4977
5052
  completed_at: Field.datetime({
4978
5053
  label: "Completed At",
4979
5054
  required: false,
@@ -6260,6 +6335,28 @@ var SETUP_APP = {
6260
6335
  { id: "nav_notifications", type: "object", label: "Notifications", objectName: "sys_notification", icon: "bell", requiresObject: "sys_notification" }
6261
6336
  ]
6262
6337
  },
6338
+ {
6339
+ id: "group_integrations",
6340
+ type: "group",
6341
+ label: "Integrations",
6342
+ icon: "plug",
6343
+ children: [
6344
+ // Outbound HTTP integrations. `sys_webhook` always ships with
6345
+ // platform-objects, so the Webhooks entry is always visible.
6346
+ // `sys_webhook_delivery` is the durable outbox row from
6347
+ // `@objectstack/plugin-webhooks/schema` — gated on `requiresObject`
6348
+ // so the Deliveries entry only renders when the plugin has been
6349
+ // wired into `defineStack({ objects: [SysWebhookDelivery, ...] })`.
6350
+ //
6351
+ // This is the canonical demonstration of "everything is an object":
6352
+ // managing webhooks (configuration) and inspecting deliveries
6353
+ // (operational telemetry) reuses the same generic ObjectView /
6354
+ // ObjectListView UI as any business object — no bespoke webhook
6355
+ // admin page.
6356
+ { id: "nav_webhooks", type: "object", label: "Webhooks", objectName: "sys_webhook", icon: "webhook", requiresObject: "sys_webhook" },
6357
+ { id: "nav_webhook_deliveries", type: "object", label: "Webhook Deliveries", objectName: "sys_webhook_delivery", icon: "send", requiresObject: "sys_webhook_delivery" }
6358
+ ]
6359
+ },
6263
6360
  {
6264
6361
  id: "group_advanced",
6265
6362
  type: "group",