@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.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,
@@ -5663,18 +5738,6 @@ var SysMetadataHistoryObject = ObjectSchema.create({
5663
5738
  readonly: true,
5664
5739
  description: "Per-organization monotonic event log cursor."
5665
5740
  }),
5666
- /**
5667
- * Parent `sys_metadata.id` at insertion time (plain text, no FK).
5668
- * Null for events whose parent row no longer exists (e.g. some
5669
- * delete records). Forensic only — joins should go through
5670
- * `(organization_id, type, name)`.
5671
- */
5672
- metadata_id: Field.text({
5673
- label: "Metadata ID",
5674
- required: false,
5675
- readonly: true,
5676
- maxLength: 64
5677
- }),
5678
5741
  /** Machine name (denormalized for easier querying) */
5679
5742
  name: Field.text({
5680
5743
  label: "Name",
@@ -5769,6 +5832,9 @@ var SysMetadataHistoryObject = ObjectSchema.create({
5769
5832
  { fields: ["organization_id", "event_seq"], unique: true },
5770
5833
  { fields: ["organization_id", "type", "name", "version"], unique: true },
5771
5834
  { fields: ["organization_id", "type", "name", "recorded_at"] },
5835
+ // ADR-0009: getByHash() lookup — execution-pinned types resolve a
5836
+ // historical body by content hash via this index.
5837
+ { fields: ["organization_id", "type", "name", "checksum"] },
5772
5838
  { fields: ["type", "name"] },
5773
5839
  { fields: ["recorded_at"] },
5774
5840
  { fields: ["operation_type"] }
@@ -6269,6 +6335,28 @@ var SETUP_APP = {
6269
6335
  { id: "nav_notifications", type: "object", label: "Notifications", objectName: "sys_notification", icon: "bell", requiresObject: "sys_notification" }
6270
6336
  ]
6271
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
+ },
6272
6360
  {
6273
6361
  id: "group_advanced",
6274
6362
  type: "group",
@@ -9263,9 +9351,6 @@ var enObjects = {
9263
9351
  id: {
9264
9352
  label: "ID"
9265
9353
  },
9266
- metadata_id: {
9267
- label: "Metadata"
9268
- },
9269
9354
  name: {
9270
9355
  label: "Name"
9271
9356
  },
@@ -12305,9 +12390,6 @@ var zhCNObjects = {
12305
12390
  id: {
12306
12391
  label: "ID"
12307
12392
  },
12308
- metadata_id: {
12309
- label: "\u5143\u6570\u636E"
12310
- },
12311
12393
  name: {
12312
12394
  label: "\u540D\u79F0"
12313
12395
  },
@@ -15293,9 +15375,6 @@ var jaJPObjects = {
15293
15375
  id: {
15294
15376
  label: "ID"
15295
15377
  },
15296
- metadata_id: {
15297
- label: "\u30E1\u30BF\u30C7\u30FC\u30BF"
15298
- },
15299
15378
  name: {
15300
15379
  label: "\u540D\u524D"
15301
15380
  },
@@ -18281,9 +18360,6 @@ var esESObjects = {
18281
18360
  id: {
18282
18361
  label: "ID"
18283
18362
  },
18284
- metadata_id: {
18285
- label: "Metadatos"
18286
- },
18287
18363
  name: {
18288
18364
  label: "Nombre"
18289
18365
  },