@git.zone/cli 3.2.0 → 4.0.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.
Files changed (126) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/classes.gitzoneconfig.js +1 -1
  3. package/dist_ts/classes.project.js +1 -1
  4. package/dist_ts/gitzone.cli.js +1 -1
  5. package/dist_ts/gitzone.logging.js +1 -1
  6. package/dist_ts/helpers.changelog.js +1 -1
  7. package/dist_ts/helpers.climode.js +1 -1
  8. package/dist_ts/helpers.smartconfig.js +61 -11
  9. package/dist_ts/helpers.smartconfigmigrations.js +1 -1
  10. package/dist_ts/helpers.tsdocker.js +1 -1
  11. package/dist_ts/helpers.workflow.js +1 -1
  12. package/dist_ts/index.js +1 -1
  13. package/dist_ts/mod_audit/index.js +1 -1
  14. package/dist_ts/mod_commit/index.js +1 -1
  15. package/dist_ts/mod_commit/mod.helpers.js +1 -1
  16. package/dist_ts/mod_commit/mod.plugins.js +1 -1
  17. package/dist_ts/mod_commit/mod.ui.js +1 -1
  18. package/dist_ts/mod_config/classes.commitconfig.js +1 -1
  19. package/dist_ts/mod_config/classes.releaseconfig.js +1 -1
  20. package/dist_ts/mod_config/index.js +2 -2
  21. package/dist_ts/mod_config/mod.plugins.js +1 -1
  22. package/dist_ts/mod_deprecate/index.js +1 -1
  23. package/dist_ts/mod_deprecate/mod.plugins.js +1 -1
  24. package/dist_ts/mod_docker/classes.dockerpruner.js +7 -1
  25. package/dist_ts/mod_docker/index.js +1 -1
  26. package/dist_ts/mod_docker/mod.plugins.js +1 -1
  27. package/dist_ts/mod_format/classes.baseformatter.js +1 -1
  28. package/dist_ts/mod_format/classes.diffreporter.js +1 -1
  29. package/dist_ts/mod_format/classes.formatcontext.js +1 -1
  30. package/dist_ts/mod_format/classes.formatplanner.js +1 -1
  31. package/dist_ts/mod_format/classes.formatstats.js +1 -1
  32. package/dist_ts/mod_format/formatters/assets.formatter.js +1 -1
  33. package/dist_ts/mod_format/formatters/cleanup.formatter.js +1 -1
  34. package/dist_ts/mod_format/formatters/copy.formatter.js +1 -1
  35. package/dist_ts/mod_format/formatters/gitignore.formatter.js +1 -1
  36. package/dist_ts/mod_format/formatters/license.formatter.js +1 -1
  37. package/dist_ts/mod_format/formatters/packagejson.formatter.js +1 -1
  38. package/dist_ts/mod_format/formatters/prettier.formatter.js +1 -1
  39. package/dist_ts/mod_format/formatters/readme.formatter.js +1 -1
  40. package/dist_ts/mod_format/formatters/smartconfig.formatter.js +1 -1
  41. package/dist_ts/mod_format/formatters/templates.formatter.js +1 -1
  42. package/dist_ts/mod_format/formatters/tsconfig.formatter.js +1 -1
  43. package/dist_ts/mod_format/index.js +1 -1
  44. package/dist_ts/mod_format/interfaces.format.js +1 -1
  45. package/dist_ts/mod_format/mod.plugins.js +1 -1
  46. package/dist_ts/mod_helpers/index.js +1 -1
  47. package/dist_ts/mod_helpers/mod.plugins.js +1 -1
  48. package/dist_ts/mod_meta/index.js +1 -1
  49. package/dist_ts/mod_meta/meta.classes.meta.js +1 -1
  50. package/dist_ts/mod_meta/meta.interfaces.js +1 -1
  51. package/dist_ts/mod_meta/meta.plugins.js +1 -1
  52. package/dist_ts/mod_open/index.js +1 -1
  53. package/dist_ts/mod_open/mod.plugins.js +1 -1
  54. package/dist_ts/mod_release/index.js +4 -4
  55. package/dist_ts/mod_release/mod.plugins.js +1 -1
  56. package/dist_ts/mod_services/classes.dockercontainer.d.ts +50 -3
  57. package/dist_ts/mod_services/classes.dockercontainer.js +646 -84
  58. package/dist_ts/mod_services/classes.globalregistry.d.ts +10 -24
  59. package/dist_ts/mod_services/classes.globalregistry.js +210 -62
  60. package/dist_ts/mod_services/classes.globalregistrystore.d.ts +48 -0
  61. package/dist_ts/mod_services/classes.globalregistrystore.js +156 -0
  62. package/dist_ts/mod_services/classes.interprocesslock.d.ts +21 -0
  63. package/dist_ts/mod_services/classes.interprocesslock.js +141 -0
  64. package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +15 -12
  65. package/dist_ts/mod_services/classes.serviceconfiguration.js +188 -91
  66. package/dist_ts/mod_services/classes.servicedatamarker.d.ts +32 -7
  67. package/dist_ts/mod_services/classes.servicedatamarker.js +145 -49
  68. package/dist_ts/mod_services/classes.servicemanager.d.ts +70 -28
  69. package/dist_ts/mod_services/classes.servicemanager.js +995 -421
  70. package/dist_ts/mod_services/classes.servicenames.d.ts +8 -0
  71. package/dist_ts/mod_services/classes.servicenames.js +54 -0
  72. package/dist_ts/mod_services/classes.serviceoptions.js +1 -1
  73. package/dist_ts/mod_services/classes.servicepruner.d.ts +3 -0
  74. package/dist_ts/mod_services/classes.servicepruner.js +208 -46
  75. package/dist_ts/mod_services/helpers.js +1 -1
  76. package/dist_ts/mod_services/index.d.ts +2 -0
  77. package/dist_ts/mod_services/index.js +81 -58
  78. package/dist_ts/mod_services/mod.plugins.js +1 -1
  79. package/dist_ts/mod_standard/index.js +2 -2
  80. package/dist_ts/mod_standard/mod.plugins.js +1 -1
  81. package/dist_ts/mod_start/index.js +1 -1
  82. package/dist_ts/mod_start/mod.plugins.js +1 -1
  83. package/dist_ts/mod_template/index.js +1 -1
  84. package/dist_ts/mod_template/mod.plugins.js +1 -1
  85. package/dist_ts/mod_tools/classes.packagemanager.js +1 -1
  86. package/dist_ts/mod_tools/index.js +1 -1
  87. package/dist_ts/mod_tools/mod.plugins.js +1 -1
  88. package/dist_ts/paths.js +1 -1
  89. package/dist_ts/plugins.d.ts +3 -1
  90. package/dist_ts/plugins.js +4 -2
  91. package/dist_ts_migration/001.service-selection.d.ts +9 -0
  92. package/dist_ts_migration/001.service-selection.js +51 -0
  93. package/dist_ts_migration/002.runtime-config.d.ts +19 -0
  94. package/dist_ts_migration/002.runtime-config.js +170 -0
  95. package/dist_ts_migration/003.service-data-marker.d.ts +9 -0
  96. package/dist_ts_migration/003.service-data-marker.js +156 -0
  97. package/dist_ts_migration/004.global-registry.d.ts +13 -0
  98. package/dist_ts_migration/004.global-registry.js +165 -0
  99. package/dist_ts_migration/index.d.ts +11 -0
  100. package/dist_ts_migration/index.js +59 -0
  101. package/package.json +6 -3
  102. package/readme.hints.md +102 -25
  103. package/readme.md +123 -28
  104. package/readme.plan.md +29 -16
  105. package/ts/00_commitinfo_data.ts +1 -1
  106. package/ts/helpers.smartconfig.ts +63 -10
  107. package/ts/mod_config/index.ts +1 -1
  108. package/ts/mod_docker/classes.dockerpruner.ts +6 -0
  109. package/ts/mod_release/index.ts +3 -3
  110. package/ts/mod_services/classes.dockercontainer.ts +912 -96
  111. package/ts/mod_services/classes.globalregistry.ts +290 -89
  112. package/ts/mod_services/classes.globalregistrystore.ts +279 -0
  113. package/ts/mod_services/classes.interprocesslock.ts +189 -0
  114. package/ts/mod_services/classes.serviceconfiguration.ts +215 -108
  115. package/ts/mod_services/classes.servicedatamarker.ts +210 -52
  116. package/ts/mod_services/classes.servicemanager.ts +1332 -512
  117. package/ts/mod_services/classes.servicenames.ts +76 -0
  118. package/ts/mod_services/classes.servicepruner.ts +310 -52
  119. package/ts/mod_services/index.ts +89 -62
  120. package/ts/mod_standard/index.ts +1 -1
  121. package/ts/plugins.ts +4 -0
  122. package/ts_migration/001.service-selection.ts +77 -0
  123. package/ts_migration/002.runtime-config.ts +218 -0
  124. package/ts_migration/003.service-data-marker.ts +216 -0
  125. package/ts_migration/004.global-registry.ts +272 -0
  126. package/ts_migration/index.ts +83 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@git.zone/cli",
3
3
  "private": false,
4
- "version": "3.2.0",
4
+ "version": "4.0.0",
5
5
  "description": "A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.",
6
6
  "main": "dist_ts/index.js",
7
7
  "typings": "dist_ts/index.d.ts",
@@ -41,15 +41,17 @@
41
41
  "devDependencies": {
42
42
  "@git.zone/tsbuild": "^4.4.2",
43
43
  "@git.zone/tsrun": "^2.0.6",
44
- "@git.zone/tstest": "^3.6.7",
45
- "@types/node": "^26.1.1"
44
+ "@git.zone/tstest": "^4.0.0",
45
+ "@types/node": "^26.2.0"
46
46
  },
47
47
  "dependencies": {
48
+ "@aws-sdk/client-s3": "3.1095.0",
48
49
  "@git.zone/tsdoc": "^2.1.1",
49
50
  "@git.zone/tspublish": "^1.11.7",
50
51
  "@push.rocks/commitinfo": "^1.0.13",
51
52
  "@push.rocks/early": "^4.0.4",
52
53
  "@push.rocks/projectinfo": "^5.1.0",
54
+ "@push.rocks/smartbucket": "4.13.0",
53
55
  "@push.rocks/smartcli": "^4.0.20",
54
56
  "@push.rocks/smartconfig": "^6.0.1",
55
57
  "@push.rocks/smartdelay": "^3.0.5",
@@ -76,6 +78,7 @@
76
78
  },
77
79
  "files": [
78
80
  "ts/**/*",
81
+ "ts_migration/**/*",
79
82
  "ts_web/**/*",
80
83
  "dist/**/*",
81
84
  "dist_*/**/*",
package/readme.hints.md CHANGED
@@ -161,19 +161,22 @@ Known remaining gaps are listed in `readme.plan.md`.
161
161
 
162
162
  ### Why data accumulated
163
163
 
164
- `gitzone services clean` never actually worked for MongoDB or MinIO. Service
165
- containers write as their own uid mongod as 999 with `drwx------` on
166
- subdirectories, MinIO as root under `.minio.sys` so a recursive delete run as
167
- the invoking user removed only the part of the tree it owned. For MongoDB the
168
- result was a half-deleted WiredTiger dataset that crash-looped on the next start
169
- (`WiredTigerHS.wt file is corrupted or missing`), kept alive indefinitely by
170
- `restart: unless-stopped`. Users hit a failing `clean`, gave up, and the data
171
- stayed. This was the root cause of multi-GB accumulation, not a missing feature.
172
-
173
- `DockerContainer.removeDataDirectory` fixes it: try a native delete, and if the
174
- directory survives, empty it from a short-lived `--user 0` container that mounts
175
- only that directory. It verifies the directory is gone and throws otherwise — a
176
- partial delete is worse than no delete.
164
+ `gitzone services clean` historically failed for service data written by a
165
+ container uid. A recursive delete run as the invoking user removed only the
166
+ part of the tree it owned. For MongoDB the result was a half-deleted WiredTiger
167
+ dataset that crash-looped on the next start (`WiredTigerHS.wt file is corrupted
168
+ or missing`), kept alive indefinitely by `restart: unless-stopped`. Users hit a
169
+ failing `clean`, gave up, and the data stayed. This was the root cause of
170
+ multi-GB accumulation, not a missing feature.
171
+
172
+ `DockerContainer.removeDataDirectory` fixes it by persisting a deletion intent
173
+ and atomically renaming the canonical path to a tokenized quarantine before any
174
+ recursive delete. Native deletion runs there; if the quarantine survives, a
175
+ short-lived root container mounts only that directory. The helper uses
176
+ shell-free Docker argv, stopped creation, exact configuration and label
177
+ inspection, and an immutable-ID fence before execution or cleanup. Interrupted
178
+ cleanup resumes the recorded quarantine, so partial work is never mistaken for
179
+ a usable canonical dataset.
177
180
 
178
181
  ### Identifying tool-owned resources
179
182
 
@@ -182,7 +185,7 @@ Follows the `git.zone.*` label convention already established by
182
185
 
183
186
  ```text
184
187
  git.zone.tool=gitzone-services
185
- git.zone.service=mongodb|minio|elasticsearch
188
+ git.zone.service=mongodb|objectstorage|elasticsearch
186
189
  git.zone.project-path=<abs path>
187
190
  git.zone.data-path=<abs path>
188
191
  git.zone.safe-to-prune=true
@@ -190,11 +193,12 @@ git.zone.safe-to-prune=true
190
193
 
191
194
  Data directories are additionally claimed by a marker at
192
195
  `<project>/.nogit/.gitzone-services.json`. The marker deliberately lives outside
193
- the bind-mounted directory so it can never confuse mongod, MinIO or
196
+ the bind-mounted directory so it can never confuse mongod, ObjectStorage or
194
197
  Elasticsearch at runtime.
195
198
 
196
- Nothing is ever matched by image or by bare name pattern. Containers predating
197
- labels are only identified when exactly one registry entry claims their name.
199
+ Nothing is ever matched by image or by bare name pattern. MongoDB and
200
+ Elasticsearch containers predating labels are identified only when exactly one
201
+ registry entry claims their name. ObjectStorage always requires exact labels.
198
202
 
199
203
  ### Prune safety model (`classes.servicepruner.ts`)
200
204
 
@@ -212,13 +216,86 @@ Invariants, enforced at plan time and again at apply time:
212
216
 
213
217
  - A data directory is never removed while any running container bind-mounts it
214
218
  or an overlapping path (`helpers.pathsOverlap`).
215
- - A path must match `<project>/.nogit/{mongodata,miniodata,esdata}` exactly
219
+ - A path must match `<project>/.nogit/{mongodata,objectstoragedata,esdata}` exactly
216
220
  (`isSafeServiceDataPath`); this is an allowlist, checked after resolution.
217
- - Ownership must be proven by marker or registry entry.
218
- - Staleness is re-checked at apply time, so a project started between plan and
219
- apply aborts the removal.
220
- - An unreachable Docker daemon disables all container and data reclamation, so
221
- ambiguity never reads as absence.
221
+ - Ownership must be proven by marker or registry entry. ObjectStorage is
222
+ stricter: an exact marker entry is required for deletion, but an exactly
223
+ label-owned canonical container can repair a missing marker before removal.
224
+ - Data-directory staleness is re-checked at apply time. Container removal
225
+ separately rechecks immutable identity, running state, ownership, and legacy
226
+ classification before mutation.
227
+ - An unreachable Docker daemon disables container, data, and registry
228
+ reclamation, so ambiguity never reads as absence.
229
+
230
+ Legacy `.nogit/miniodata` is deliberately outside the allowlist. Marker
231
+ migration retains that path with `safeToPrune: false`; registry migration
232
+ retains the legacy container reference separately. The service and general
233
+ Docker pruners reject legacy MinIO containers, and service prune rejects
234
+ bind-operation helpers again at apply time.
235
+
236
+ ### ObjectStorage migration and lifecycle
237
+
238
+ `objectstorage` is the canonical service identifier and `s3` is its user-facing
239
+ alias. Persisted `minio` and `s3` entries migrate to the same canonical flat
240
+ array value because `@git.zone/cli.services` remains a tsdeploy capability
241
+ input. New CLI input does not accept the provider name `minio`.
242
+
243
+ The active container is `<project>-objectstorage`, its data path is
244
+ `.nogit/objectstoragedata`, and its image is pinned by manifest-list digest.
245
+ Ports `9000` and `3000` are published as the configured API and UI ports on
246
+ `127.0.0.1`. `S3_ADMIN_PASSWORD`, `S3_REGION`, and `S3_UI_PORT` are
247
+ ObjectStorage-specific runtime fields. Existing generic fields such as
248
+ `S3_ENDPOINT`, `S3_HOST`, and `S3_USESSL` are preserved rather than silently
249
+ rewritten; internal reconciliation always targets loopback explicitly.
250
+
251
+ Startup first rejects legacy `<project>-minio` containers, registry-retained
252
+ alternate legacy names, and `.nogit/miniodata`, then proves exact labels on any
253
+ canonical same-name container. Exact container proof can repair a missing valid
254
+ data marker; invalid or foreign markers remain blocking. Drift reconciliation
255
+ covers the complete runtime contract, including
256
+ the exact set of `OBJST_*` and `UI_PORT` controls while allowing unrelated image
257
+ environment, and all subsequent Docker mutations use the discovered immutable
258
+ ID. A shared 30-second deadline bounds Docker setup, `/readyz`, authenticated
259
+ bucket lookup/creation, and verification. SmartBucket provides its own bounded,
260
+ idempotent client cleanup. A pre-existing ID enters rollback only after `docker
261
+ start` succeeds; an uncertain pre-existing start remains adoptable because
262
+ state inspection cannot prove which concurrent invocation caused the transition.
263
+
264
+ The v2 marker and global registry schemas separate canonical ObjectStorage from
265
+ legacy MinIO evidence. Legacy evidence is detection-only: never activate it,
266
+ reinterpret its disk data, pass it to lifecycle methods, or make it reclaimable.
267
+ Migration validates every selected store before the first write, then revalidates
268
+ each store at its own apply boundary. Closed-schema selection, marker, and
269
+ registry state rejects malformed, foreign, conflicting, or future shapes.
270
+ Runtime config validates known fields while preserving unknown fields. The
271
+ global registry uses a shared atomic-mkdir transaction lock, fresh raw reads,
272
+ fsynced same-directory
273
+ replacement writes, and compare-delete for unregister operations. Lock ownership
274
+ is token-checked and release first renames to an invocation tombstone. Stale locks
275
+ are never broken automatically; the error reports the exact lock path for manual
276
+ inspection after the recorded process is known to be gone.
277
+
278
+ The same lock primitive protects runtime-config migration and saves, marker
279
+ migration and ownership recording, and each service's start/delete data-path
280
+ critical section. Runtime config saves compare the bytes loaded by that instance
281
+ with the current file before replacement, so a stale command cannot overwrite a
282
+ newer port or credential change. Marker writers re-read inside the lock and merge
283
+ claims. Start and stop refresh config inside a global per-project/service lock.
284
+ Data deletion rechecks labeled stopped containers and all configured mounts
285
+ inside that lock; a preserved stopped container blocks its project's data from
286
+ becoming reclaimable. Before recursive deletion, an exact persisted intent
287
+ atomically moves the canonical directory to a tokenized quarantine. Interrupted
288
+ or partial cleanup resumes only that recorded path and cannot leave a corrupt
289
+ canonical dataset. Every service startup rejects a pending deletion intent so a
290
+ fresh canonical directory cannot strand quarantined data.
291
+
292
+ Bind-operation helpers use one deterministic Docker name per host target as an
293
+ atomic helper-level lock. Each create adds a random invocation label and a
294
+ stable ownership-spec label. Uncertain creates are polled within the rollback
295
+ deadline and may be removed only when the invocation label matches. A later
296
+ operation may remove an old stopped canonical helper by non-forced immutable-ID
297
+ removal; fresh, running, or noncanonical occupants fail closed. This lock covers
298
+ the root helper operations, not the entire service start/clean command.
222
299
 
223
300
  ### MongoDB auth modes
224
301
 
@@ -389,8 +466,8 @@ The project has been fully migrated from @push.rocks/smartfile v11 to v13, which
389
466
 
390
467
  **Packages:**
391
468
 
392
- - `@push.rocks/smartfile` v13.0.1 - File representation classes (SmartFile, StreamFile, VirtualDirectory)
393
- - `@push.rocks/smartfs` v1.1.0 - Filesystem operations (read, write, exists, stat, etc.)
469
+ - `@push.rocks/smartfile` v13.1.3 - File representation classes (SmartFile, StreamFile, VirtualDirectory)
470
+ - `@push.rocks/smartfs` v1.6.0 - Filesystem operations (read, write, exists, stat, etc.)
394
471
 
395
472
  **Key API Changes:**
396
473
 
package/readme.md CHANGED
@@ -56,7 +56,7 @@ gitzone release
56
56
  | `release` | Turn pending changelog entries into a versioned release and publish targets |
57
57
  | `format` | Plan or apply project formatting and standardization |
58
58
  | `config` | Inspect, update, and migrate `.smartconfig.json` |
59
- | `services` | Manage local MongoDB, MinIO, and Elasticsearch containers |
59
+ | `services` | Manage local MongoDB, ObjectStorage, and Elasticsearch containers |
60
60
  | `tools` | Manage the global `@git.zone` toolchain |
61
61
  | `template` | Scaffold projects from built-in templates |
62
62
  | `meta` | Manage multi-repository workspaces |
@@ -452,18 +452,21 @@ Formatters include cleanup, smartconfig normalization, dependency license checks
452
452
 
453
453
  Supported services:
454
454
 
455
- | Service | Aliases |
455
+ | Service | Lifecycle/log aliases |
456
456
  | --- | --- |
457
457
  | MongoDB | `mongo`, `mongodb` |
458
- | MinIO | `minio`, `s3` |
458
+ | ObjectStorage (S3-compatible) | `objectstorage`, `s3` |
459
459
  | Elasticsearch | `elasticsearch`, `es` |
460
460
 
461
+ Service-selection commands such as `set`, `enable`, and `disable` also accept
462
+ `elastic`; lifecycle and log commands do not.
463
+
461
464
  ```bash
462
465
  # Start configured services
463
466
  gitzone services start
464
467
 
465
468
  # Enable specific services non-interactively
466
- gitzone services set mongodb,minio
469
+ gitzone services set mongodb,objectstorage
467
470
 
468
471
  # Check status
469
472
  gitzone services status
@@ -478,21 +481,81 @@ gitzone services compass
478
481
  gitzone services logs mongo 50
479
482
  ```
480
483
 
481
- Service config is stored in `.nogit/env.json`. Data is stored below `.nogit/`, so it stays out of Git.
482
-
483
- GitZone derives new MinIO bucket names from the project name using S3 naming
484
- rules. When loading older configuration it repairs only the exact generated
484
+ Service config is stored in `.nogit/env.json`. Newly created config files use
485
+ owner-only permissions; writes are atomic and reject a stale in-memory snapshot
486
+ rather than overwriting a concurrent change. MongoDB, ObjectStorage, and
487
+ Elasticsearch data is stored in `.nogit/mongodata`,
488
+ `.nogit/objectstoragedata`, and `.nogit/esdata`, so it stays out of Git.
489
+
490
+ ObjectStorage uses `S3_PORT` for its local S3 API and `S3_UI_PORT` for its
491
+ management UI. `S3_REGION` defaults to `us-east-1`; `S3_ADMIN_PASSWORD` is a
492
+ separate randomly generated password for the UI's `admin` user. Startup rejects
493
+ empty credentials, `admin`/`admin` S3 defaults, the default admin password, and
494
+ an admin password reused as either S3 credential. `gitzone services config
495
+ --json` replaces those three ObjectStorage credential values with `"***"`.
496
+ Other fields are unchanged, including MongoDB and Elasticsearch passwords and
497
+ credential-bearing URLs, so the complete output must still be treated as
498
+ sensitive.
499
+
500
+ GitZone runs a digest-pinned ObjectStorage image with both the S3 API and
501
+ management UI published on loopback. `S3_HOST`, `S3_ENDPOINT`, `S3_USESSL`, and
502
+ the other generic S3 consumer fields remain user-controlled; service startup
503
+ always reconciles the local managed instance through `127.0.0.1` and its
504
+ configured local ports.
505
+
506
+ GitZone derives new bucket names from the project name using S3 naming rules.
507
+ When loading older configuration it repairs only the exact generated
485
508
  `<project>-documents` value if that value is invalid; custom bucket names are
486
- never rewritten. `services start minio` validates custom names, recreates a
487
- container whose configured credentials or ports drifted, authenticates the
488
- configured alias, creates the bucket idempotently, and verifies it before
489
- reporting success. Before GitZone starts, recreates, or executes inside an
490
- existing MinIO container, current-project ownership must be proven by exact
491
- GitZone labels or one unambiguous legacy registry claim. Every lifecycle
492
- operation after discovery uses the container's immutable id. If startup fails,
493
- GitZone stops only containers that this invocation started; it never stops a
494
- container that was already running. Invalid custom names do not block read-only
495
- or recovery commands such as `status`, `logs`, `stop`, `remove`, and `clean`.
509
+ never rewritten. `services start s3` validates the bucket and credentials,
510
+ recreates an owned container when its pinned image, ports, data bind, controlled
511
+ product environment, restart policy, command, entrypoint, user, or health check
512
+ drifted, waits for management readiness, then creates and verifies the bucket
513
+ through an authenticated S3 client. A GitZone-label mismatch is an ownership
514
+ conflict and blocks mutation rather than being treated as repairable drift.
515
+ Container setup, management readiness, and the S3 operations share one deadline;
516
+ SmartBucket cleanup has its own bounded close. Docker mutations use the
517
+ container's immutable ID after exact-name discovery.
518
+ On failure, GitZone stops a pre-existing container only after that invocation's
519
+ start returned successfully. A newly created ID remains invocation-owned across
520
+ an uncertain start and can be stopped safely; an uncertain pre-existing start is
521
+ left adoptable rather than risking stopping another concurrent invocation. A
522
+ canonical container created but not yet started remains stopped for a safe retry.
523
+
524
+ ### Migrating legacy MinIO state
525
+
526
+ Persisted `minio` and `s3` service selections are rewritten to the canonical
527
+ `objectstorage` value. `S3_CONSOLE_PORT` is migrated to `S3_UI_PORT` when the
528
+ values do not conflict. The runtime migration also adds the separate admin
529
+ password and region fields and repairs only the exact invalid bucket name that
530
+ older GitZone versions generated. Legacy registry and data-marker entries are
531
+ retained as preserved migration evidence, not converted into active
532
+ ObjectStorage ownership. Every selected migration store is preflighted before
533
+ the first write. Closed-schema service selection, marker, and registry stores
534
+ reject malformed, conflicting, foreign, or future state without rewriting it.
535
+ Runtime config validates and migrates its known fields while preserving unknown
536
+ application fields.
537
+
538
+ If `<project>-minio`, a registry-retained alternate legacy container name, or
539
+ `.nogit/miniodata` still exists, ObjectStorage startup stops before mutating the
540
+ ObjectStorage container. In an untargeted `services start`, an earlier enabled
541
+ service such as MongoDB may already have started. GitZone never reuses, removes,
542
+ cleans, or prunes legacy MinIO state because its disk layout is not compatible
543
+ with ObjectStorage. Recovery is explicit:
544
+
545
+ 1. Export every required bucket with the existing MinIO tooling.
546
+ 2. Stop and rename the legacy container, then move `.nogit/miniodata` to a preserved backup location.
547
+ 3. Run `gitzone services start s3` to create the canonical service.
548
+ 4. Import through an external S3 client and verify the required objects before disposing of the backup.
549
+
550
+ An existing `.nogit/objectstoragedata` directory without a valid ownership
551
+ marker blocks creation of a new container and direct cleanup. One exception is
552
+ an existing container whose immutable identity and exact canonical GitZone
553
+ labels prove that directory belongs to this project; startup or removal repairs
554
+ the missing marker before proceeding. An invalid or foreign marker always
555
+ blocks mutation. Without that exact container proof, preserve or move the
556
+ directory, verify its provenance outside GitZone, start a fresh canonical
557
+ service, and import required objects through S3. Do not synthesize a marker for
558
+ unverified data.
496
559
 
497
560
  ### Consuming a service programmatically
498
561
 
@@ -503,6 +566,13 @@ script can read a live connection string without parsing human output:
503
566
  gitzone services status --json | jq -r '.services.mongodb.connectionString'
504
567
  ```
505
568
 
569
+ The ObjectStorage status key is `.services.objectstorage`; the former
570
+ `.services.minio` key no longer exists. Preserved predecessor evidence is
571
+ reported separately under `.legacy`. `minioDataDirectory` and `minioDataExists`
572
+ are always emitted; `minioContainer` is present only when container evidence
573
+ exists. Consumers must treat this as a breaking response-schema change rather
574
+ than interpreting legacy evidence as an active service.
575
+
506
576
  ### Cleanup levels
507
577
 
508
578
  Cleanup is tiered, from fully resumable to irreversible:
@@ -514,10 +584,26 @@ Cleanup is tiered, from fully resumable to irreversible:
514
584
  | `gitzone services clean` | removed | **removed** | irreversible; needs a typed `yes` or `--yes` |
515
585
  | `gitzone services prune` | see below | see below | machine-wide; dry run unless `--apply` |
516
586
 
517
- `clean` and `prune` remove data written by the container user (mongod runs as
518
- uid 999, MinIO as root) by escalating to a short-lived privileged container
519
- scoped to that one directory. They either remove a directory completely or fail
520
- a partial delete would leave a corrupt database behind.
587
+ `clean` and `prune` first persist an exact deletion intent, then atomically rename
588
+ the canonical directory to a tokenized sibling quarantine before deleting any
589
+ contents. Native deletion is attempted there. If container-owned files remain,
590
+ GitZone uses a short-lived root container scoped to that quarantine; Docker's
591
+ `--privileged` mode is not used. The helper reserves one deterministic name per
592
+ bind target, carries a random invocation label, is created stopped, and is
593
+ inspected by immutable ID before execution or cleanup. Old stopped helpers can
594
+ be recovered only after their complete runtime envelope, bind target, age, and
595
+ immutable ID are proven; running, fresh, or noncanonical occupants block the
596
+ operation. If interruption or helper failure leaves bytes, the persisted intent
597
+ lets the next `clean` or `prune --apply` resume the same quarantine. A partial
598
+ failure therefore never leaves a corrupt directory at the canonical service
599
+ path. Startup refuses to create fresh service data while such an intent remains.
600
+
601
+ Service start, stop, container removal, and data removal share one interprocess
602
+ lock per project and service. Startup refreshes runtime config and project
603
+ activity inside that lock, while prune rechecks activity and stopped as well as
604
+ running service containers after acquiring it. Concurrent lifecycle commands
605
+ therefore serialize rather than deleting a directory or container while another
606
+ command prepares, mounts, starts, or stops it.
521
607
 
522
608
  ### Reclaiming space across projects
523
609
 
@@ -541,9 +627,18 @@ with: its directory is gone, or it has been inactive past the threshold with no
541
627
  container running. Anything ambiguous — an unlabeled container claimed by more
542
628
  than one project, an unreachable Docker daemon, a directory still mounted by a
543
629
  running container — is reported and skipped rather than reclaimed. Containers
544
- are identified by the `git.zone.tool=gitzone-services` label or by an
545
- unambiguous registry claim, never by image or name pattern, so pruning cannot
546
- touch containers created by anything else.
630
+ are identified by an exact canonical GitZone label envelope. An unambiguous
631
+ registry claim is used only for older MongoDB and Elasticsearch containers with
632
+ no `git.zone.*` labels at all. ObjectStorage has no unlabeled predecessor
633
+ fallback; partial, missing, or conflicting GitZone labels fail closed. Removal
634
+ revalidates and uses the container's immutable ID, never its mutable name, so
635
+ pruning cannot touch a same-name replacement. If Docker becomes unavailable,
636
+ registry claims are preserved as well as containers and data.
637
+
638
+ Legacy MinIO containers and registry references are reported as preserved
639
+ migration resources and are never prune candidates. `.nogit/miniodata` is
640
+ deliberately outside the prune allowlist; current-project `status` reports its
641
+ presence, while machine-wide prune leaves it untouched.
547
642
 
548
643
  ### MongoDB authentication
549
644
 
@@ -608,11 +703,11 @@ make it look like an older version is installed when it is not:
608
703
 
609
704
  ```bash
610
705
  gitzone --version
611
- # 2.25.0
612
- # resolved from: /home/you/.local/share/pnpm/store/v11/links/@git.zone/cli/2.25.0/…
706
+ # 3.2.1
707
+ # resolved from: /home/you/.local/share/pnpm/store/v11/links/@git.zone/cli/3.2.1/…
613
708
 
614
709
  gitzone --version --json
615
- # {"version":"2.25.0","resolvedFrom":"…"}
710
+ # {"version":"3.2.1","resolvedFrom":"…"}
616
711
  ```
617
712
 
618
713
  `gitzone tools update` also removes inert copies of managed packages left behind
package/readme.plan.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Overview
4
4
 
5
- Implement the `gitzone services` command to manage MongoDB and MinIO containers for development projects.
5
+ Implement the `gitzone services` command to manage MongoDB, ObjectStorage, and Elasticsearch containers for development projects.
6
6
 
7
7
  ## Tasks
8
8
 
@@ -33,7 +33,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
33
33
 
34
34
  - [x] Implement ServiceManager class
35
35
  - [x] Manage MongoDB containers
36
- - [x] Manage MinIO containers
36
+ - [x] Manage ObjectStorage containers
37
37
  - [x] Handle container lifecycle
38
38
  - [x] Generate project-specific container names
39
39
  - [x] Manage data directories in `.nogit/`
@@ -41,9 +41,9 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
41
41
 
42
42
  ### Commands Implementation
43
43
 
44
- - [x] `start` command - Start services (mongo|s3|all)
45
- - [x] `stop` command - Stop services (mongo|s3|all)
46
- - [x] `restart` command - Restart services (mongo|s3|all)
44
+ - [x] `start` command - Start enabled services or target mongo|objectstorage|s3|elasticsearch
45
+ - [x] `stop` command - Stop all services or target mongo|objectstorage|s3|elasticsearch
46
+ - [x] `restart` command - Stop all then start enabled services, or restart target mongo|objectstorage|s3|elasticsearch
47
47
  - [x] `status` command - Show service status
48
48
  - [x] `config` command - Show current configuration
49
49
  - [x] `compass` command - Show MongoDB Compass connection string
@@ -55,7 +55,7 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
55
55
 
56
56
  - [x] Add `@push.rocks/smartshell` to main plugins.ts
57
57
  - [x] Add `@push.rocks/smartnetwork` to main plugins.ts
58
- - [x] Add `@push.rocks/smartinteraction` to main plugins.ts
58
+ - [x] Add `@push.rocks/smartinteract` to main plugins.ts
59
59
  - [x] Register services command in `gitzone.cli.ts`
60
60
 
61
61
  ### Features
@@ -67,13 +67,13 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
67
67
  - [x] Status display (running/stopped/not installed)
68
68
  - [x] Interactive confirmations for destructive operations
69
69
  - [x] Colored console output
70
- - [x] MinIO bucket auto-creation
70
+ - [x] ObjectStorage bucket auto-creation and authenticated verification
71
71
  - [x] MongoDB Compass connection string with network IP
72
72
 
73
73
  ### Testing
74
74
 
75
- - [ ] Test service start/stop operations
76
- - [ ] Test configuration creation and updates
75
+ - [x] Test service start/stop operations
76
+ - [x] Test configuration creation and updates
77
77
  - [ ] Test port collision handling
78
78
  - [ ] Test data persistence
79
79
  - [ ] Test MongoDB Compass connection string generation
@@ -89,19 +89,30 @@ Implement the `gitzone services` command to manage MongoDB and MinIO containers
89
89
  "MONGODB_PORT": "random-port",
90
90
  "MONGODB_USER": "defaultadmin",
91
91
  "MONGODB_PASS": "defaultpass",
92
+ "MONGODB_URL": "derived connection URL",
93
+ "MONGODB_AUTH_ENABLED": true,
92
94
  "S3_HOST": "localhost",
93
95
  "S3_PORT": "random-port",
94
- "S3_CONSOLE_PORT": "s3-port+1",
95
- "S3_USER": "defaultadmin",
96
- "S3_PASS": "defaultpass",
97
- "S3_BUCKET": "project-name-documents"
96
+ "S3_UI_PORT": "first available port at or above s3-port+1",
97
+ "S3_ACCESSKEY": "defaultadmin",
98
+ "S3_SECRETKEY": "defaultpass",
99
+ "S3_ADMIN_PASSWORD": "random-secret",
100
+ "S3_REGION": "us-east-1",
101
+ "S3_BUCKET": "project-name-documents",
102
+ "S3_ENDPOINT": "localhost",
103
+ "S3_USESSL": false,
104
+ "ELASTICSEARCH_HOST": "localhost",
105
+ "ELASTICSEARCH_PORT": "9200",
106
+ "ELASTICSEARCH_USER": "elastic",
107
+ "ELASTICSEARCH_PASS": "elastic",
108
+ "ELASTICSEARCH_URL": "derived connection URL"
98
109
  }
99
110
  ```
100
111
 
101
112
  ## Command Examples
102
113
 
103
114
  ```bash
104
- gitzone services start # Start all services
115
+ gitzone services start # Start all enabled services
105
116
  gitzone services start mongo # Start only MongoDB
106
117
  gitzone services stop # Stop all services
107
118
  gitzone services status # Check service status
@@ -121,7 +132,7 @@ Implementation completed: 2025-08-14
121
132
 
122
133
  Successfully implemented the `gitzone services` command in TypeScript, providing a complete replacement for the `services.sh` shell script. The implementation includes:
123
134
 
124
- 1. **Complete Docker service management** for MongoDB and MinIO containers
135
+ 1. **Complete Docker service management** for MongoDB, ObjectStorage, and Elasticsearch containers
125
136
  2. **Smart configuration management** with automatic port assignment and conflict avoidance
126
137
  3. **MongoDB Compass support** with network IP detection for remote connections
127
138
  4. **Project isolation** using project-specific container names
@@ -129,7 +140,9 @@ Successfully implemented the `gitzone services` command in TypeScript, providing
129
140
  6. **Interactive confirmations** for destructive operations
130
141
  7. **Comprehensive command set** including start, stop, restart, status, config, compass, logs, remove, and clean commands
131
142
 
132
- The module is fully integrated into the gitzone CLI and ready for testing.
143
+ The module is integrated into the gitzone CLI and covered by unit tests. A real
144
+ authenticated Docker smoke still requires an explicitly isolated harness; it
145
+ must never run against user-managed containers.
133
146
 
134
147
  ## Destructive-command audit — remaining items
135
148
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/cli',
6
- version: '3.2.0',
6
+ version: '4.0.0',
7
7
  description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.'
8
8
  }