@objectstack/platform-objects 9.11.0 → 10.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.
@@ -378,6 +378,19 @@ var SysUser = data.ObjectSchema.create({
378
378
  required: false,
379
379
  group: "Profile"
380
380
  }),
381
+ // ── Organization ─────────────────────────────────────────────
382
+ manager_id: data.Field.lookup("sys_user", {
383
+ label: "Manager",
384
+ required: false,
385
+ group: "Organization",
386
+ description: "This user's direct manager. Forms the reporting chain the `own_and_reports` hierarchy scope walks (ADR-0057 / @objectstack/security-enterprise)."
387
+ }),
388
+ primary_business_unit_id: data.Field.lookup("sys_business_unit", {
389
+ label: "Primary Business Unit",
390
+ required: false,
391
+ group: "Organization",
392
+ description: "The user's primary business unit \u2014 a denormalised projection of sys_business_unit_member.is_primary, maintained by plugin-sharing (ADR-0057 addendum D12). Lets a user-lookup filter candidates by business unit without traversing the membership junction. Do not edit directly; set it via business-unit membership."
393
+ }),
381
394
  // ── System (auto-managed, hidden from create/edit forms) ─────
382
395
  id: data.Field.text({
383
396
  label: "User ID",
@@ -1158,7 +1171,10 @@ var SysMember = data.ObjectSchema.create({
1158
1171
  }),
1159
1172
  organization_id: data.Field.lookup("sys_organization", {
1160
1173
  label: "Organization",
1161
- required: true
1174
+ // Optional: single-tenant has no sys_organization row and no auto-stamp
1175
+ // (org-scoping is multi-tenant-only). Multi-tenant: OrgScopingPlugin stamps it
1176
+ // and tenant-isolation RLS hides null-org rows (fail-closed). ADR-0057 addendum.
1177
+ required: false
1162
1178
  }),
1163
1179
  user_id: data.Field.lookup("sys_user", {
1164
1180
  label: "User",
@@ -1345,7 +1361,10 @@ var SysInvitation = data.ObjectSchema.create({
1345
1361
  }),
1346
1362
  organization_id: data.Field.lookup("sys_organization", {
1347
1363
  label: "Organization",
1348
- required: true
1364
+ // Optional: single-tenant has no sys_organization row and no auto-stamp
1365
+ // (org-scoping is multi-tenant-only). Multi-tenant: OrgScopingPlugin stamps it
1366
+ // and tenant-isolation RLS hides null-org rows (fail-closed). ADR-0057 addendum.
1367
+ required: false
1349
1368
  }),
1350
1369
  email: data.Field.email({
1351
1370
  label: "Email",
@@ -1505,8 +1524,13 @@ var SysTeam = data.ObjectSchema.create({
1505
1524
  }),
1506
1525
  organization_id: data.Field.lookup("sys_organization", {
1507
1526
  label: "Organization",
1508
- required: true,
1509
- description: "Parent organization for this team",
1527
+ // Optional: single-tenant deployments have no organization row (org-scoping
1528
+ // is multi-tenant-only, nothing auto-stamps one) — requiring it would make
1529
+ // the object uncreatable single-tenant. In multi-tenant, OrgScopingPlugin
1530
+ // auto-stamps this from the active tenant and tenant-isolation RLS hides any
1531
+ // null-org row (fail-closed). ADR-0057 addendum.
1532
+ required: false,
1533
+ description: "Parent organization for this team. Null in single-tenant; auto-stamped in multi-tenant.",
1510
1534
  group: "Identity"
1511
1535
  }),
1512
1536
  // ── System ───────────────────────────────────────────────────
@@ -1635,24 +1659,42 @@ var SysTeamMember = data.ObjectSchema.create({
1635
1659
  mru: false
1636
1660
  }
1637
1661
  });
1638
- var SysDepartment = data.ObjectSchema.create({
1639
- name: "sys_department",
1640
- label: "Department",
1641
- pluralLabel: "Departments",
1662
+ var SysBusinessUnit = data.ObjectSchema.create({
1663
+ name: "sys_business_unit",
1664
+ label: "Business Unit",
1665
+ pluralLabel: "Business Units",
1642
1666
  icon: "building",
1643
1667
  isSystem: true,
1644
1668
  managedBy: "platform",
1645
- description: "Hierarchical org-skeleton node (department / division / business unit / office).",
1669
+ description: "Canonical Business Unit tree \u2014 hierarchical org/data-partition node (company / division / department / region / office). ADR-0057 D2.",
1646
1670
  displayNameField: "name",
1647
1671
  titleFormat: "{name}",
1648
- compactLayout: ["name", "kind", "parent_department_id", "manager_user_id"],
1672
+ compactLayout: ["name", "kind", "parent_business_unit_id", "manager_user_id"],
1649
1673
  listViews: {
1674
+ // Org chart — the hierarchy view. Surfaces the self-referencing
1675
+ // `parent_business_unit_id` tree (ADR-0057 D2) as an indented, expand/
1676
+ // collapse tree-grid. Listed first so it's the default tab; the grids
1677
+ // below stay for search / filter / bulk edit.
1678
+ org_chart: {
1679
+ type: "tree",
1680
+ name: "org_chart",
1681
+ label: "Org Chart",
1682
+ data: { provider: "object", object: "sys_business_unit" },
1683
+ columns: ["name", "kind", "manager_user_id", "active"],
1684
+ tree: {
1685
+ parentField: "parent_business_unit_id",
1686
+ labelField: "name",
1687
+ fields: ["kind", "manager_user_id", "active"],
1688
+ defaultExpandedDepth: 1
1689
+ },
1690
+ sort: [{ field: "name", order: "asc" }]
1691
+ },
1650
1692
  active: {
1651
1693
  type: "grid",
1652
1694
  name: "active",
1653
1695
  label: "Active",
1654
- data: { provider: "object", object: "sys_department" },
1655
- columns: ["name", "code", "kind", "parent_department_id", "manager_user_id", "effective_from"],
1696
+ data: { provider: "object", object: "sys_business_unit" },
1697
+ columns: ["name", "code", "kind", "parent_business_unit_id", "manager_user_id", "effective_from"],
1656
1698
  filter: [{ field: "active", operator: "equals", value: true }],
1657
1699
  sort: [{ field: "name", order: "asc" }],
1658
1700
  pagination: { pageSize: 100 }
@@ -1661,7 +1703,7 @@ var SysDepartment = data.ObjectSchema.create({
1661
1703
  type: "grid",
1662
1704
  name: "inactive",
1663
1705
  label: "Inactive",
1664
- data: { provider: "object", object: "sys_department" },
1706
+ data: { provider: "object", object: "sys_business_unit" },
1665
1707
  columns: ["name", "code", "kind", "effective_to"],
1666
1708
  filter: [{ field: "active", operator: "equals", value: false }],
1667
1709
  sort: [{ field: "effective_to", order: "desc" }],
@@ -1671,8 +1713,8 @@ var SysDepartment = data.ObjectSchema.create({
1671
1713
  type: "grid",
1672
1714
  name: "by_kind",
1673
1715
  label: "By Kind",
1674
- data: { provider: "object", object: "sys_department" },
1675
- columns: ["kind", "name", "code", "parent_department_id", "manager_user_id", "active"],
1716
+ data: { provider: "object", object: "sys_business_unit" },
1717
+ columns: ["kind", "name", "code", "parent_business_unit_id", "manager_user_id", "active"],
1676
1718
  sort: [{ field: "kind", order: "asc" }, { field: "name", order: "asc" }],
1677
1719
  grouping: { fields: [{ field: "kind", order: "asc", collapsed: false }] },
1678
1720
  pagination: { pageSize: 100 }
@@ -1681,8 +1723,8 @@ var SysDepartment = data.ObjectSchema.create({
1681
1723
  type: "grid",
1682
1724
  name: "all_departments",
1683
1725
  label: "All",
1684
- data: { provider: "object", object: "sys_department" },
1685
- columns: ["name", "code", "kind", "parent_department_id", "manager_user_id", "active"],
1726
+ data: { provider: "object", object: "sys_business_unit" },
1727
+ columns: ["name", "code", "kind", "parent_business_unit_id", "manager_user_id", "active"],
1686
1728
  sort: [{ field: "name", order: "asc" }],
1687
1729
  pagination: { pageSize: 100 }
1688
1730
  }
@@ -1705,7 +1747,7 @@ var SysDepartment = data.ObjectSchema.create({
1705
1747
  group: "Identity"
1706
1748
  }),
1707
1749
  kind: data.Field.select(
1708
- ["company", "division", "department", "team", "office", "cost_center"],
1750
+ ["company", "division", "department", "office", "cost_center"],
1709
1751
  {
1710
1752
  label: "Kind",
1711
1753
  required: true,
@@ -1715,23 +1757,28 @@ var SysDepartment = data.ObjectSchema.create({
1715
1757
  }
1716
1758
  ),
1717
1759
  // ── Hierarchy ────────────────────────────────────────────────
1718
- parent_department_id: data.Field.lookup("sys_department", {
1719
- label: "Parent Department",
1760
+ parent_business_unit_id: data.Field.lookup("sys_business_unit", {
1761
+ label: "Parent Business Unit",
1720
1762
  required: false,
1721
1763
  description: "Self-reference for the org tree. Null = root of tenant.",
1722
1764
  group: "Hierarchy"
1723
1765
  }),
1724
1766
  organization_id: data.Field.lookup("sys_organization", {
1725
1767
  label: "Organization",
1726
- required: true,
1727
- description: "Tenant scope.",
1768
+ // Optional: single-tenant deployments have no organization row (org-scoping
1769
+ // is multi-tenant-only, nothing auto-stamps one) — requiring it would make
1770
+ // the object uncreatable single-tenant. In multi-tenant, OrgScopingPlugin
1771
+ // auto-stamps this from the active tenant and tenant-isolation RLS hides any
1772
+ // null-org row (fail-closed). ADR-0057 addendum.
1773
+ required: false,
1774
+ description: "Tenant scope. Null in single-tenant; auto-stamped in multi-tenant.",
1728
1775
  group: "Hierarchy"
1729
1776
  }),
1730
1777
  // ── Leadership ───────────────────────────────────────────────
1731
1778
  manager_user_id: data.Field.lookup("sys_user", {
1732
- label: "Department Head",
1779
+ label: "Business Unit Head",
1733
1780
  required: false,
1734
- description: "User responsible for this org unit (department head / lead).",
1781
+ description: "User responsible for this org unit (business unit head / lead).",
1735
1782
  group: "Leadership"
1736
1783
  }),
1737
1784
  // ── Lifecycle ────────────────────────────────────────────────
@@ -1745,13 +1792,13 @@ var SysDepartment = data.ObjectSchema.create({
1745
1792
  effective_from: data.Field.datetime({
1746
1793
  label: "Effective From",
1747
1794
  required: false,
1748
- description: "When this department came into existence (HRIS sync).",
1795
+ description: "When this business unit came into existence (HRIS sync).",
1749
1796
  group: "Lifecycle"
1750
1797
  }),
1751
1798
  effective_to: data.Field.datetime({
1752
1799
  label: "Effective To",
1753
1800
  required: false,
1754
- description: "When this department was retired (HRIS sync).",
1801
+ description: "When this business unit was retired (HRIS sync).",
1755
1802
  group: "Lifecycle"
1756
1803
  }),
1757
1804
  external_ref: data.Field.text({
@@ -1763,7 +1810,7 @@ var SysDepartment = data.ObjectSchema.create({
1763
1810
  }),
1764
1811
  // ── System ───────────────────────────────────────────────────
1765
1812
  id: data.Field.text({
1766
- label: "Department ID",
1813
+ label: "Business Unit ID",
1767
1814
  required: true,
1768
1815
  readonly: true,
1769
1816
  group: "System"
@@ -1783,7 +1830,7 @@ var SysDepartment = data.ObjectSchema.create({
1783
1830
  },
1784
1831
  indexes: [
1785
1832
  { fields: ["organization_id"] },
1786
- { fields: ["parent_department_id"] },
1833
+ { fields: ["parent_business_unit_id"] },
1787
1834
  { fields: ["code", "organization_id"], unique: true },
1788
1835
  { fields: ["active"] }
1789
1836
  ],
@@ -1796,16 +1843,16 @@ var SysDepartment = data.ObjectSchema.create({
1796
1843
  mru: false
1797
1844
  }
1798
1845
  });
1799
- var SysDepartmentMember = data.ObjectSchema.create({
1800
- name: "sys_department_member",
1801
- label: "Department Member",
1802
- pluralLabel: "Department Members",
1846
+ var SysBusinessUnitMember = data.ObjectSchema.create({
1847
+ name: "sys_business_unit_member",
1848
+ label: "Business Unit Member",
1849
+ pluralLabel: "Business Unit Members",
1803
1850
  icon: "user-cog",
1804
1851
  isSystem: true,
1805
1852
  managedBy: "platform",
1806
- description: "User assignment to a department (matrix-org friendly, effective-dated).",
1807
- titleFormat: "{user_id} in {department_id}",
1808
- compactLayout: ["user_id", "department_id", "role_in_department", "is_primary"],
1853
+ description: "User assignment to a business unit (matrix-org friendly, effective-dated).",
1854
+ titleFormat: "{user_id} in {business_unit_id}",
1855
+ compactLayout: ["user_id", "business_unit_id", "role_in_business_unit", "is_primary"],
1809
1856
  fields: {
1810
1857
  id: data.Field.text({
1811
1858
  label: "Member ID",
@@ -1813,8 +1860,8 @@ var SysDepartmentMember = data.ObjectSchema.create({
1813
1860
  readonly: true,
1814
1861
  group: "System"
1815
1862
  }),
1816
- department_id: data.Field.lookup("sys_department", {
1817
- label: "Department",
1863
+ business_unit_id: data.Field.lookup("sys_business_unit", {
1864
+ label: "Business Unit",
1818
1865
  required: true,
1819
1866
  group: "Assignment"
1820
1867
  }),
@@ -1823,10 +1870,10 @@ var SysDepartmentMember = data.ObjectSchema.create({
1823
1870
  required: true,
1824
1871
  group: "Assignment"
1825
1872
  }),
1826
- role_in_department: data.Field.select(
1873
+ role_in_business_unit: data.Field.select(
1827
1874
  ["member", "lead", "deputy"],
1828
1875
  {
1829
- label: "Role in Department",
1876
+ label: "Role in Business Unit",
1830
1877
  required: false,
1831
1878
  defaultValue: "member",
1832
1879
  description: "`lead` is the day-to-day head; `deputy` may stand in for the lead in approval routing.",
@@ -1837,7 +1884,7 @@ var SysDepartmentMember = data.ObjectSchema.create({
1837
1884
  label: "Primary Assignment",
1838
1885
  required: false,
1839
1886
  defaultValue: true,
1840
- description: "When the user is in multiple departments, this marks the canonical one for reporting.",
1887
+ description: "When the user is in multiple business units, this marks the canonical one for reporting.",
1841
1888
  group: "Assignment"
1842
1889
  }),
1843
1890
  effective_from: data.Field.datetime({
@@ -1864,7 +1911,7 @@ var SysDepartmentMember = data.ObjectSchema.create({
1864
1911
  })
1865
1912
  },
1866
1913
  indexes: [
1867
- { fields: ["department_id", "user_id"], unique: true },
1914
+ { fields: ["business_unit_id", "user_id"], unique: true },
1868
1915
  { fields: ["user_id"] },
1869
1916
  { fields: ["is_primary"] }
1870
1917
  ],
@@ -3112,8 +3159,8 @@ var SysJwks = data.ObjectSchema.create({
3112
3159
 
3113
3160
  exports.SysAccount = SysAccount;
3114
3161
  exports.SysApiKey = SysApiKey;
3115
- exports.SysDepartment = SysDepartment;
3116
- exports.SysDepartmentMember = SysDepartmentMember;
3162
+ exports.SysBusinessUnit = SysBusinessUnit;
3163
+ exports.SysBusinessUnitMember = SysBusinessUnitMember;
3117
3164
  exports.SysDeviceCode = SysDeviceCode;
3118
3165
  exports.SysInvitation = SysInvitation;
3119
3166
  exports.SysJwks = SysJwks;