@objectstack/platform-objects 5.0.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.js CHANGED
@@ -3268,6 +3268,20 @@ var defaultPermissionSets = [
3268
3268
  operation: "select",
3269
3269
  using: "id = current_user.id"
3270
3270
  },
3271
+ // Org collaborators: members can see other users in the same
3272
+ // organization. Without this, owner/assignee lookups, @-mention
3273
+ // suggestions, reviewer pickers and team-roster surfaces all
3274
+ // collapse to just the current user. `org_user_ids` is
3275
+ // pre-resolved by runtime/resolve-execution-context from
3276
+ // `sys_member` for the active organization. Sensitive credential
3277
+ // tables (`sys_account`, `sys_session`, `sys_api_key`, …) keep
3278
+ // their stricter self-only carve-outs above.
3279
+ {
3280
+ name: "sys_user_org_members",
3281
+ object: "sys_user",
3282
+ operation: "select",
3283
+ using: "id IN (current_user.org_user_ids)"
3284
+ },
3271
3285
  {
3272
3286
  name: "sys_session_self",
3273
3287
  object: "sys_session",
@@ -3365,8 +3379,14 @@ var defaultPermissionSets = [
3365
3379
  operation: "select",
3366
3380
  using: "id = current_user.id"
3367
3381
  },
3368
- // ── Per-user visibility on better-auth tables that lack
3369
- // `organization_id` (matches the `member_default` carve-outs).
3382
+ // Org collaborators (read-only): see `sys_user_org_members` in
3383
+ // `member_default` for rationale.
3384
+ {
3385
+ name: "sys_user_org_members",
3386
+ object: "sys_user",
3387
+ operation: "select",
3388
+ using: "id IN (current_user.org_user_ids)"
3389
+ },
3370
3390
  {
3371
3391
  name: "sys_session_self",
3372
3392
  object: "sys_session",
@@ -4093,13 +4113,56 @@ var SysNotification = data.ObjectSchema.create({
4093
4113
  displayNameField: "title",
4094
4114
  titleFormat: "{title}",
4095
4115
  compactLayout: ["title", "type", "is_read", "created_at"],
4116
+ /**
4117
+ * Row-level inbox actions. Use `visible` CEL expressions to ensure
4118
+ * `mark_read` only shows on unread rows and vice-versa, mirroring the
4119
+ * mark-as-read affordances in GitHub / Linear inboxes. The toolbar-level
4120
+ * `mark_all_read` is intentionally omitted server-side: it requires a
4121
+ * bulk update primitive that doesn't yet exist on the REST surface, and
4122
+ * the popover already handles the multi-row case client-side via N
4123
+ * single-row PATCHes (see `InboxPopover.tsx` -> AppHeader `markAllRead`).
4124
+ */
4125
+ actions: [
4126
+ {
4127
+ name: "mark_read",
4128
+ label: "Mark as Read",
4129
+ icon: "check",
4130
+ variant: "secondary",
4131
+ mode: "custom",
4132
+ locations: ["list_item"],
4133
+ type: "api",
4134
+ method: "PATCH",
4135
+ target: "/api/v1/data/sys_notification/{id}",
4136
+ bodyExtra: { is_read: true },
4137
+ visible: "!record.is_read",
4138
+ successMessage: "Notification marked as read",
4139
+ refreshAfter: true
4140
+ },
4141
+ {
4142
+ name: "mark_unread",
4143
+ label: "Mark as Unread",
4144
+ icon: "bell-dot",
4145
+ variant: "secondary",
4146
+ mode: "custom",
4147
+ locations: ["list_item"],
4148
+ type: "api",
4149
+ method: "PATCH",
4150
+ target: "/api/v1/data/sys_notification/{id}",
4151
+ bodyExtra: { is_read: false, read_at: null },
4152
+ visible: "record.is_read",
4153
+ successMessage: "Notification marked as unread",
4154
+ refreshAfter: true
4155
+ }
4156
+ ],
4096
4157
  listViews: {
4097
4158
  unread: {
4098
4159
  type: "grid",
4099
4160
  name: "unread",
4100
4161
  label: "Unread",
4101
4162
  data: { provider: "object", object: "sys_notification" },
4102
- columns: ["type", "title", "recipient_id", "created_at"],
4163
+ // Title + actor first (the "who/what" the user actually scans);
4164
+ // type stays as a categorising chip; created_at right-aligned.
4165
+ columns: ["title", "actor_name", "type", "created_at"],
4103
4166
  filter: [
4104
4167
  { field: "recipient_id", operator: "equals", value: "{current_user_id}" },
4105
4168
  { field: "is_read", operator: "equals", value: false }
@@ -4113,17 +4176,21 @@ var SysNotification = data.ObjectSchema.create({
4113
4176
  name: "mine",
4114
4177
  label: "Mine",
4115
4178
  data: { provider: "object", object: "sys_notification" },
4116
- columns: ["type", "title", "is_read", "created_at"],
4179
+ columns: ["title", "actor_name", "type", "is_read", "created_at"],
4117
4180
  filter: [{ field: "recipient_id", operator: "equals", value: "{current_user_id}" }],
4118
4181
  sort: [{ field: "created_at", order: "desc" }],
4119
- pagination: { pageSize: 50 }
4182
+ pagination: { pageSize: 50 },
4183
+ // Group by notification category so mention/assignment storms don't
4184
+ // hide system or task_due rows. Users still toggle to flat via the
4185
+ // toolbar Group control if they prefer chronology only.
4186
+ grouping: { fields: [{ field: "type", order: "asc", collapsed: false }] }
4120
4187
  },
4121
4188
  all_notifications: {
4122
4189
  type: "grid",
4123
4190
  name: "all_notifications",
4124
4191
  label: "All",
4125
4192
  data: { provider: "object", object: "sys_notification" },
4126
- columns: ["type", "title", "recipient_id", "is_read", "created_at"],
4193
+ columns: ["title", "recipient_id", "actor_name", "type", "is_read", "created_at"],
4127
4194
  sort: [{ field: "created_at", order: "desc" }],
4128
4195
  pagination: { pageSize: 100 }
4129
4196
  }
@@ -4976,6 +5043,14 @@ var SysApprovalRequest = data.ObjectSchema.create({
4976
5043
  description: "Record snapshot at submission time",
4977
5044
  group: "State"
4978
5045
  }),
5046
+ process_hash: data.Field.text({
5047
+ label: "Process Hash",
5048
+ required: false,
5049
+ maxLength: 80,
5050
+ readonly: true,
5051
+ 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.",
5052
+ group: "State"
5053
+ }),
4979
5054
  completed_at: data.Field.datetime({
4980
5055
  label: "Completed At",
4981
5056
  required: false,
@@ -5665,18 +5740,6 @@ var SysMetadataHistoryObject = data.ObjectSchema.create({
5665
5740
  readonly: true,
5666
5741
  description: "Per-organization monotonic event log cursor."
5667
5742
  }),
5668
- /**
5669
- * Parent `sys_metadata.id` at insertion time (plain text, no FK).
5670
- * Null for events whose parent row no longer exists (e.g. some
5671
- * delete records). Forensic only — joins should go through
5672
- * `(organization_id, type, name)`.
5673
- */
5674
- metadata_id: data.Field.text({
5675
- label: "Metadata ID",
5676
- required: false,
5677
- readonly: true,
5678
- maxLength: 64
5679
- }),
5680
5743
  /** Machine name (denormalized for easier querying) */
5681
5744
  name: data.Field.text({
5682
5745
  label: "Name",
@@ -5771,6 +5834,9 @@ var SysMetadataHistoryObject = data.ObjectSchema.create({
5771
5834
  { fields: ["organization_id", "event_seq"], unique: true },
5772
5835
  { fields: ["organization_id", "type", "name", "version"], unique: true },
5773
5836
  { fields: ["organization_id", "type", "name", "recorded_at"] },
5837
+ // ADR-0009: getByHash() lookup — execution-pinned types resolve a
5838
+ // historical body by content hash via this index.
5839
+ { fields: ["organization_id", "type", "name", "checksum"] },
5774
5840
  { fields: ["type", "name"] },
5775
5841
  { fields: ["recorded_at"] },
5776
5842
  { fields: ["operation_type"] }
@@ -6271,6 +6337,28 @@ var SETUP_APP = {
6271
6337
  { id: "nav_notifications", type: "object", label: "Notifications", objectName: "sys_notification", icon: "bell", requiresObject: "sys_notification" }
6272
6338
  ]
6273
6339
  },
6340
+ {
6341
+ id: "group_integrations",
6342
+ type: "group",
6343
+ label: "Integrations",
6344
+ icon: "plug",
6345
+ children: [
6346
+ // Outbound HTTP integrations. `sys_webhook` always ships with
6347
+ // platform-objects, so the Webhooks entry is always visible.
6348
+ // `sys_webhook_delivery` is the durable outbox row from
6349
+ // `@objectstack/plugin-webhooks/schema` — gated on `requiresObject`
6350
+ // so the Deliveries entry only renders when the plugin has been
6351
+ // wired into `defineStack({ objects: [SysWebhookDelivery, ...] })`.
6352
+ //
6353
+ // This is the canonical demonstration of "everything is an object":
6354
+ // managing webhooks (configuration) and inspecting deliveries
6355
+ // (operational telemetry) reuses the same generic ObjectView /
6356
+ // ObjectListView UI as any business object — no bespoke webhook
6357
+ // admin page.
6358
+ { id: "nav_webhooks", type: "object", label: "Webhooks", objectName: "sys_webhook", icon: "webhook", requiresObject: "sys_webhook" },
6359
+ { id: "nav_webhook_deliveries", type: "object", label: "Webhook Deliveries", objectName: "sys_webhook_delivery", icon: "send", requiresObject: "sys_webhook_delivery" }
6360
+ ]
6361
+ },
6274
6362
  {
6275
6363
  id: "group_advanced",
6276
6364
  type: "group",
@@ -9265,9 +9353,6 @@ var enObjects = {
9265
9353
  id: {
9266
9354
  label: "ID"
9267
9355
  },
9268
- metadata_id: {
9269
- label: "Metadata"
9270
- },
9271
9356
  name: {
9272
9357
  label: "Name"
9273
9358
  },
@@ -12307,9 +12392,6 @@ var zhCNObjects = {
12307
12392
  id: {
12308
12393
  label: "ID"
12309
12394
  },
12310
- metadata_id: {
12311
- label: "\u5143\u6570\u636E"
12312
- },
12313
12395
  name: {
12314
12396
  label: "\u540D\u79F0"
12315
12397
  },
@@ -15295,9 +15377,6 @@ var jaJPObjects = {
15295
15377
  id: {
15296
15378
  label: "ID"
15297
15379
  },
15298
- metadata_id: {
15299
- label: "\u30E1\u30BF\u30C7\u30FC\u30BF"
15300
- },
15301
15380
  name: {
15302
15381
  label: "\u540D\u524D"
15303
15382
  },
@@ -18283,9 +18362,6 @@ var esESObjects = {
18283
18362
  id: {
18284
18363
  label: "ID"
18285
18364
  },
18286
- metadata_id: {
18287
- label: "Metadatos"
18288
- },
18289
18365
  name: {
18290
18366
  label: "Nombre"
18291
18367
  },