@@ -5,10 +5,20 @@ import { ObjectSchema, Field } from '@objectstack/spec/data';
55/**
66 * sys_package_installation — Per-environment package installation record.
77 *
8- * Tracks which packages (business solutions) are installed in each environment.
9- * Stored in the **Control Plane** (sys namespace → turso driver) so that all
10- * environment installations are visible from a single query. Environment DBs
11- * contain only business data rows — zero system tables.
8+ * Models the pairing between an environment and a specific, immutable package
9+ * version snapshot (`sys_package_version`). Only one version of a given package
10+ * may be active per environment at a time (enforced by UNIQUE on
11+ * `(environment_id, package_id)`).
12+ *
13+ * **Upgrade** = atomic UPDATE of `package_version_id` to a newer version UUID.
14+ * **Rollback** = atomic UPDATE of `package_version_id` to an older version UUID.
15+ * Version history is tracked via the sequence of `package_version_id` changes
16+ * on this row (and an optional sys_package_installation_history audit table).
17+ *
18+ * **Stored in the Control Plane DB (not in environment DBs).**
19+ * Environment DBs contain only business data rows — zero system tables.
20+ *
21+ * See `docs/adr/0003-package-as-first-class-citizen.md` for the full rationale.
1222 *
1323 * @namespace sys
1424 */
@@ -19,106 +29,111 @@ export const SysPackageInstallation = ObjectSchema.create({
1929 pluralLabel : 'Package Installations' ,
2030 icon : 'package' ,
2131 isSystem : true ,
22- description : 'Per-environment package installation registry (sys_package_installation)' ,
32+ description : 'Per-environment package installation registry (sys_package_installation). ' ,
2333 titleFormat : '{package_id} @ {environment_id}' ,
24- compactLayout : [ 'package_id ' , 'environment_id' , 'version ' , 'status ' ] ,
34+ compactLayout : [ 'package_version_id ' , 'environment_id' , 'status ' , 'installed_at ' ] ,
2535
2636 fields : {
2737 id : Field . text ( {
2838 label : 'Installation ID' ,
2939 required : true ,
3040 readonly : true ,
31- description : 'UUID-based installation identifier ' ,
41+ description : 'UUID of this installation record (stable, never reused). ' ,
3242 } ) ,
3343
3444 created_at : Field . datetime ( {
3545 label : 'Created At' ,
3646 defaultValue : 'NOW()' ,
3747 readonly : true ,
48+ description : 'Creation timestamp (ISO-8601).' ,
3849 } ) ,
3950
4051 updated_at : Field . datetime ( {
4152 label : 'Updated At' ,
4253 defaultValue : 'NOW()' ,
4354 readonly : true ,
55+ description : 'Last update timestamp — changes on upgrade, rollback, enable/disable (ISO-8601).' ,
4456 } ) ,
4557
4658 environment_id : Field . text ( {
4759 label : 'Environment ID' ,
4860 required : true ,
49- description : 'Foreign key to sys__environment ' ,
61+ description : 'Foreign key to sys_environment (UUID). The environment that owns this installation. ' ,
5062 } ) ,
5163
52- package_id : Field . text ( {
53- label : 'Package ID' ,
64+ package_version_id : Field . text ( {
65+ label : 'Package Version ID' ,
5466 required : true ,
55- maxLength : 255 ,
56- description : 'Manifest ID of the installed package (reverse-domain, e.g. com.example.crm)' ,
67+ description :
68+ 'Foreign key to sys_package_version (UUID). The specific, immutable release snapshot ' +
69+ 'currently installed in this environment. Upgrading = swapping this field to a newer ' +
70+ 'version UUID. Rollback = swapping to an older version UUID.' ,
5771 } ) ,
5872
59- version : Field . text ( {
60- label : 'Version ' ,
73+ package_id : Field . text ( {
74+ label : 'Package ID ' ,
6175 required : true ,
62- maxLength : 50 ,
63- description : 'Installed package version (semver)' ,
76+ description :
77+ 'Foreign key to sys_package (UUID). Denormalized from the linked package_version row ' +
78+ 'at install time to enforce the UNIQUE (environment_id, package_id) constraint without a JOIN.' ,
6479 } ) ,
6580
6681 status : Field . select ( {
6782 label : 'Status' ,
6883 required : true ,
84+ defaultValue : 'installed' ,
85+ description : 'Current lifecycle status of this installation within the environment.' ,
6986 options : [
7087 { value : 'installed' , label : 'Installed' } ,
7188 { value : 'installing' , label : 'Installing' } ,
7289 { value : 'upgrading' , label : 'Upgrading' } ,
7390 { value : 'disabled' , label : 'Disabled' } ,
7491 { value : 'error' , label : 'Error' } ,
7592 ] ,
76- defaultValue : 'installed' ,
7793 } ) ,
7894
7995 enabled : Field . boolean ( {
8096 label : 'Enabled' ,
8197 required : true ,
8298 defaultValue : true ,
83- description : 'Whether the package is currently active in this environment' ,
99+ description :
100+ 'Whether the package metadata is actively loaded into this environment. ' +
101+ 'Disabled packages are installed but their schema is not visible to the runtime.' ,
102+ } ) ,
103+
104+ settings : Field . textarea ( {
105+ label : 'Settings' ,
106+ required : false ,
107+ description :
108+ 'JSON-serialized per-installation configuration overrides. ' +
109+ 'Keys mirror the package manifest configurationSchema.properties.' ,
84110 } ) ,
85111
86112 installed_at : Field . datetime ( {
87113 label : 'Installed At' ,
88114 required : true ,
89115 defaultValue : 'NOW()' ,
116+ description : 'Timestamp when this installation was first created (ISO-8601).' ,
90117 } ) ,
91118
92119 installed_by : Field . text ( {
93120 label : 'Installed By' ,
94121 required : false ,
95- description : 'User ID who installed the package ' ,
122+ description : 'User ID who performed the initial install. Null for system-automated installs. ' ,
96123 } ) ,
97124
98125 error_message : Field . textarea ( {
99126 label : 'Error Message' ,
100127 required : false ,
101- description : 'Error details when status is error' ,
102- } ) ,
103-
104- settings : Field . textarea ( {
105- label : 'Settings' ,
106- required : false ,
107- description : 'JSON-serialized per-installation configuration' ,
108- } ) ,
109-
110- upgrade_history : Field . textarea ( {
111- label : 'Upgrade History' ,
112- required : false ,
113- defaultValue : '[]' ,
114- description : 'JSON array of version upgrade records' ,
128+ description : 'Error details when status is error. Cleared on next successful install/upgrade.' ,
115129 } ) ,
116130 } ,
117131
118132 indexes : [
119133 { fields : [ 'environment_id' , 'package_id' ] , unique : true } ,
120134 { fields : [ 'environment_id' ] } ,
121135 { fields : [ 'package_id' ] } ,
136+ { fields : [ 'package_version_id' ] } ,
122137 { fields : [ 'status' ] } ,
123138 ] ,
124139
0 commit comments