@git.zone/cli 3.2.1 → 5.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 (135) hide show
  1. package/.smartconfig.json +0 -1
  2. package/dist_ts/00_commitinfo_data.js +2 -2
  3. package/dist_ts/classes.gitzoneconfig.js +1 -1
  4. package/dist_ts/classes.project.js +1 -1
  5. package/dist_ts/gitzone.cli.js +1 -1
  6. package/dist_ts/gitzone.logging.js +1 -1
  7. package/dist_ts/helpers.changelog.js +1 -1
  8. package/dist_ts/helpers.climode.js +1 -1
  9. package/dist_ts/helpers.smartconfig.js +61 -11
  10. package/dist_ts/helpers.smartconfigmigrations.js +1 -1
  11. package/dist_ts/helpers.tsdocker.js +1 -1
  12. package/dist_ts/helpers.workflow.d.ts +0 -2
  13. package/dist_ts/helpers.workflow.js +23 -12
  14. package/dist_ts/index.js +1 -1
  15. package/dist_ts/mod_audit/index.js +1 -1
  16. package/dist_ts/mod_commit/index.js +1 -1
  17. package/dist_ts/mod_commit/mod.helpers.d.ts +3 -3
  18. package/dist_ts/mod_commit/mod.helpers.js +10 -10
  19. package/dist_ts/mod_commit/mod.plugins.js +1 -1
  20. package/dist_ts/mod_commit/mod.ui.js +1 -1
  21. package/dist_ts/mod_config/classes.commitconfig.js +1 -1
  22. package/dist_ts/mod_config/classes.releaseconfig.js +1 -1
  23. package/dist_ts/mod_config/index.js +23 -24
  24. package/dist_ts/mod_config/mod.plugins.js +1 -1
  25. package/dist_ts/mod_deprecate/index.js +1 -1
  26. package/dist_ts/mod_deprecate/mod.plugins.js +1 -1
  27. package/dist_ts/mod_docker/classes.dockerpruner.js +7 -1
  28. package/dist_ts/mod_docker/index.js +1 -1
  29. package/dist_ts/mod_docker/mod.plugins.js +1 -1
  30. package/dist_ts/mod_format/classes.baseformatter.js +1 -1
  31. package/dist_ts/mod_format/classes.diffreporter.js +1 -1
  32. package/dist_ts/mod_format/classes.formatcontext.js +1 -1
  33. package/dist_ts/mod_format/classes.formatplanner.js +1 -1
  34. package/dist_ts/mod_format/classes.formatstats.js +1 -1
  35. package/dist_ts/mod_format/formatters/assets.formatter.js +1 -1
  36. package/dist_ts/mod_format/formatters/cleanup.formatter.js +1 -1
  37. package/dist_ts/mod_format/formatters/copy.formatter.js +1 -1
  38. package/dist_ts/mod_format/formatters/gitignore.formatter.js +1 -1
  39. package/dist_ts/mod_format/formatters/license.formatter.js +1 -1
  40. package/dist_ts/mod_format/formatters/packagejson.formatter.js +1 -1
  41. package/dist_ts/mod_format/formatters/prettier.formatter.js +1 -1
  42. package/dist_ts/mod_format/formatters/readme.formatter.js +1 -1
  43. package/dist_ts/mod_format/formatters/smartconfig.formatter.js +1 -1
  44. package/dist_ts/mod_format/formatters/templates.formatter.js +1 -1
  45. package/dist_ts/mod_format/formatters/tsconfig.formatter.js +1 -1
  46. package/dist_ts/mod_format/index.js +1 -1
  47. package/dist_ts/mod_format/interfaces.format.js +1 -1
  48. package/dist_ts/mod_format/mod.plugins.js +1 -1
  49. package/dist_ts/mod_helpers/index.js +1 -1
  50. package/dist_ts/mod_helpers/mod.plugins.js +1 -1
  51. package/dist_ts/mod_meta/index.js +1 -1
  52. package/dist_ts/mod_meta/meta.classes.meta.js +1 -1
  53. package/dist_ts/mod_meta/meta.interfaces.js +1 -1
  54. package/dist_ts/mod_meta/meta.plugins.js +1 -1
  55. package/dist_ts/mod_open/index.js +1 -1
  56. package/dist_ts/mod_open/mod.plugins.js +1 -1
  57. package/dist_ts/mod_release/helpers.releasebranch.d.ts +46 -0
  58. package/dist_ts/mod_release/helpers.releasebranch.js +579 -0
  59. package/dist_ts/mod_release/index.d.ts +10 -0
  60. package/dist_ts/mod_release/index.js +300 -92
  61. package/dist_ts/mod_release/mod.plugins.js +1 -1
  62. package/dist_ts/mod_services/classes.dockercontainer.d.ts +50 -3
  63. package/dist_ts/mod_services/classes.dockercontainer.js +646 -84
  64. package/dist_ts/mod_services/classes.globalregistry.d.ts +10 -24
  65. package/dist_ts/mod_services/classes.globalregistry.js +210 -62
  66. package/dist_ts/mod_services/classes.globalregistrystore.d.ts +48 -0
  67. package/dist_ts/mod_services/classes.globalregistrystore.js +156 -0
  68. package/dist_ts/mod_services/classes.interprocesslock.d.ts +21 -0
  69. package/dist_ts/mod_services/classes.interprocesslock.js +141 -0
  70. package/dist_ts/mod_services/classes.serviceconfiguration.d.ts +15 -12
  71. package/dist_ts/mod_services/classes.serviceconfiguration.js +188 -91
  72. package/dist_ts/mod_services/classes.servicedatamarker.d.ts +32 -7
  73. package/dist_ts/mod_services/classes.servicedatamarker.js +145 -49
  74. package/dist_ts/mod_services/classes.servicemanager.d.ts +70 -28
  75. package/dist_ts/mod_services/classes.servicemanager.js +995 -421
  76. package/dist_ts/mod_services/classes.servicenames.d.ts +8 -0
  77. package/dist_ts/mod_services/classes.servicenames.js +54 -0
  78. package/dist_ts/mod_services/classes.serviceoptions.js +1 -1
  79. package/dist_ts/mod_services/classes.servicepruner.d.ts +3 -0
  80. package/dist_ts/mod_services/classes.servicepruner.js +208 -46
  81. package/dist_ts/mod_services/helpers.js +1 -1
  82. package/dist_ts/mod_services/index.d.ts +2 -0
  83. package/dist_ts/mod_services/index.js +81 -58
  84. package/dist_ts/mod_services/mod.plugins.js +1 -1
  85. package/dist_ts/mod_standard/index.js +2 -2
  86. package/dist_ts/mod_standard/mod.plugins.js +1 -1
  87. package/dist_ts/mod_start/index.js +1 -1
  88. package/dist_ts/mod_start/mod.plugins.js +1 -1
  89. package/dist_ts/mod_template/index.js +1 -1
  90. package/dist_ts/mod_template/mod.plugins.js +1 -1
  91. package/dist_ts/mod_tools/classes.packagemanager.js +1 -1
  92. package/dist_ts/mod_tools/index.js +1 -1
  93. package/dist_ts/mod_tools/mod.plugins.js +1 -1
  94. package/dist_ts/paths.js +1 -1
  95. package/dist_ts/plugins.d.ts +3 -1
  96. package/dist_ts/plugins.js +4 -2
  97. package/dist_ts_migration/001.service-selection.d.ts +9 -0
  98. package/dist_ts_migration/001.service-selection.js +51 -0
  99. package/dist_ts_migration/002.runtime-config.d.ts +19 -0
  100. package/dist_ts_migration/002.runtime-config.js +170 -0
  101. package/dist_ts_migration/003.service-data-marker.d.ts +9 -0
  102. package/dist_ts_migration/003.service-data-marker.js +156 -0
  103. package/dist_ts_migration/004.global-registry.d.ts +13 -0
  104. package/dist_ts_migration/004.global-registry.js +165 -0
  105. package/dist_ts_migration/index.d.ts +11 -0
  106. package/dist_ts_migration/index.js +59 -0
  107. package/package.json +6 -3
  108. package/readme.hints.md +102 -25
  109. package/readme.md +144 -41
  110. package/readme.plan.md +29 -16
  111. package/ts/00_commitinfo_data.ts +1 -1
  112. package/ts/helpers.smartconfig.ts +63 -10
  113. package/ts/helpers.workflow.ts +41 -12
  114. package/ts/mod_commit/mod.helpers.ts +12 -8
  115. package/ts/mod_config/index.ts +22 -23
  116. package/ts/mod_docker/classes.dockerpruner.ts +6 -0
  117. package/ts/mod_release/helpers.releasebranch.ts +1282 -0
  118. package/ts/mod_release/index.ts +608 -129
  119. package/ts/mod_services/classes.dockercontainer.ts +912 -96
  120. package/ts/mod_services/classes.globalregistry.ts +290 -89
  121. package/ts/mod_services/classes.globalregistrystore.ts +279 -0
  122. package/ts/mod_services/classes.interprocesslock.ts +189 -0
  123. package/ts/mod_services/classes.serviceconfiguration.ts +215 -108
  124. package/ts/mod_services/classes.servicedatamarker.ts +210 -52
  125. package/ts/mod_services/classes.servicemanager.ts +1332 -512
  126. package/ts/mod_services/classes.servicenames.ts +76 -0
  127. package/ts/mod_services/classes.servicepruner.ts +310 -52
  128. package/ts/mod_services/index.ts +89 -62
  129. package/ts/mod_standard/index.ts +1 -1
  130. package/ts/plugins.ts +4 -0
  131. package/ts_migration/001.service-selection.ts +77 -0
  132. package/ts_migration/002.runtime-config.ts +218 -0
  133. package/ts_migration/003.service-data-marker.ts +216 -0
  134. package/ts_migration/004.global-registry.ts +272 -0
  135. 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.1",
4
+ "version": "5.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 |
@@ -133,23 +133,28 @@ Commit flags:
133
133
 
134
134
  ## Release Workflow
135
135
 
136
- `gitzone release` performs the release core once, then publishes to configured targets.
136
+ `gitzone release` releases from `main`. Running it on another branch fails before release metadata or ref mutation unless the bare `--merge` flag is explicitly supplied.
137
+
138
+ `--merge` is intentionally strict: the source and existing `main` worktree must be clean, the source must be linearly rebased onto current remote `main`, and the Git target must push both the branch and tag. GitZone pins the single configured push URL, compare-and-swap fast-forwards local `main`, updates its verified worktree, and lease-pushes that exact source commit before creating release metadata. It rejects diverged or merged history, local replacement refs or grafts, stale worktrees, incomplete shallow history, changed destinations, and remote races. If the pre-release push fails, GitZone restores local `main` only when doing so cannot overwrite concurrent work. This plumbing-level integration intentionally does not run merge hooks or write `ORIG_HEAD`.
139
+
140
+ `gitzone release` performs the release core once, then publishes to configured targets. An active Git target must succeed before npm or Docker publication can start.
137
141
 
138
142
  The release core is not configurable plumbing. It always follows the same professional release transaction:
139
143
 
140
- 1. Run configured preflight checks.
141
- 2. Read `changelog.md` `## Pending` entries.
142
- 3. Infer or accept a semver bump.
143
- 4. Update version files and baked commit info.
144
- 5. Move pending changelog entries into the new version section.
145
- 6. Create the local release commit.
146
- 7. Create the local release tag.
144
+ 1. Verify the release branch, clean state, and `main` worktree ownership.
145
+ 2. Read `changelog.md` `## Pending` entries and infer or accept a semver bump.
146
+ 3. Run configured tests.
147
+ 4. With `--merge`, fast-forward and lease-push `main` before release metadata is created.
148
+ 5. Update version files and baked commit info.
149
+ 6. Move pending changelog entries into the new version section.
150
+ 7. Create the local release commit and tag on `main`.
151
+ 8. Run the configured release build, require a clean tree, and revalidate the release checkout.
147
152
 
148
153
  Targets decide what happens after that:
149
154
 
150
155
  | Target | What it does |
151
156
  | --- | --- |
152
- | `git` | Pushes the release commit and tags, often triggering remote CI release builds |
157
+ | `git` | Atomically pushes the exact `main` release commit and new tag, often triggering remote CI release builds |
153
158
  | `npm` | Publishes the package to configured npm registries |
154
159
  | `docker` | Delegates container builds and pushes to `tsdocker` |
155
160
 
@@ -160,6 +165,9 @@ gitzone release --plan
160
165
  # Release to configured targets
161
166
  gitzone release
162
167
 
168
+ # From a clean feature branch already rebased onto current main
169
+ gitzone release --merge
170
+
163
171
  # Release only to npm
164
172
  gitzone release --target npm
165
173
 
@@ -179,15 +187,16 @@ Release flags:
179
187
  | --- | --- |
180
188
  | `-y`, `--yes` | Run without interactive confirmation |
181
189
  | `-t`, `--test` | Enable preflight tests |
182
- | `-b`, `--build` | Enable preflight build |
190
+ | `-b`, `--build` | Enable the release build after local release metadata is created |
183
191
  | `-p`, `--push` | Enable the `git` target |
184
192
  | `--target <csv>` | Use only selected targets, e.g. `git,npm` |
185
193
  | `--npm` | Enable the `npm` target |
186
194
  | `--docker` | Enable the `docker` target |
187
195
  | `--no-publish` | Keep release core and `git` target only |
188
- | `--no-build` | Disable preflight build for this run |
196
+ | `--no-build` | Disable the post-metadata release build for this run |
197
+ | `--merge` | Fast-forward and lease-push a cleanly rebased feature branch into `main`, then release from `main` |
189
198
  | `--major`, `--minor`, `--patch` | Override inferred semver level |
190
- | `--plan` | Show resolved workflow only |
199
+ | `--plan` | Show the resolved workflow without fetching or mutating refs, files, the index, or worktrees |
191
200
 
192
201
  ## Standard Changelog
193
202
 
@@ -223,7 +232,6 @@ CLI workflow config lives under `@git.zone/cli` in `.smartconfig.json`. Docker b
223
232
  "release": {
224
233
  "confirmation": "prompt",
225
234
  "preflight": {
226
- "requireCleanTree": true,
227
235
  "test": false,
228
236
  "build": true
229
237
  },
@@ -452,18 +460,21 @@ Formatters include cleanup, smartconfig normalization, dependency license checks
452
460
 
453
461
  Supported services:
454
462
 
455
- | Service | Aliases |
463
+ | Service | Lifecycle/log aliases |
456
464
  | --- | --- |
457
465
  | MongoDB | `mongo`, `mongodb` |
458
- | MinIO | `minio`, `s3` |
466
+ | ObjectStorage (S3-compatible) | `objectstorage`, `s3` |
459
467
  | Elasticsearch | `elasticsearch`, `es` |
460
468
 
469
+ Service-selection commands such as `set`, `enable`, and `disable` also accept
470
+ `elastic`; lifecycle and log commands do not.
471
+
461
472
  ```bash
462
473
  # Start configured services
463
474
  gitzone services start
464
475
 
465
476
  # Enable specific services non-interactively
466
- gitzone services set mongodb,minio
477
+ gitzone services set mongodb,objectstorage
467
478
 
468
479
  # Check status
469
480
  gitzone services status
@@ -478,21 +489,81 @@ gitzone services compass
478
489
  gitzone services logs mongo 50
479
490
  ```
480
491
 
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
492
+ Service config is stored in `.nogit/env.json`. Newly created config files use
493
+ owner-only permissions; writes are atomic and reject a stale in-memory snapshot
494
+ rather than overwriting a concurrent change. MongoDB, ObjectStorage, and
495
+ Elasticsearch data is stored in `.nogit/mongodata`,
496
+ `.nogit/objectstoragedata`, and `.nogit/esdata`, so it stays out of Git.
497
+
498
+ ObjectStorage uses `S3_PORT` for its local S3 API and `S3_UI_PORT` for its
499
+ management UI. `S3_REGION` defaults to `us-east-1`; `S3_ADMIN_PASSWORD` is a
500
+ separate randomly generated password for the UI's `admin` user. Startup rejects
501
+ empty credentials, `admin`/`admin` S3 defaults, the default admin password, and
502
+ an admin password reused as either S3 credential. `gitzone services config
503
+ --json` replaces those three ObjectStorage credential values with `"***"`.
504
+ Other fields are unchanged, including MongoDB and Elasticsearch passwords and
505
+ credential-bearing URLs, so the complete output must still be treated as
506
+ sensitive.
507
+
508
+ GitZone runs a digest-pinned ObjectStorage image with both the S3 API and
509
+ management UI published on loopback. `S3_HOST`, `S3_ENDPOINT`, `S3_USESSL`, and
510
+ the other generic S3 consumer fields remain user-controlled; service startup
511
+ always reconciles the local managed instance through `127.0.0.1` and its
512
+ configured local ports.
513
+
514
+ GitZone derives new bucket names from the project name using S3 naming rules.
515
+ When loading older configuration it repairs only the exact generated
485
516
  `<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`.
517
+ never rewritten. `services start s3` validates the bucket and credentials,
518
+ recreates an owned container when its pinned image, ports, data bind, controlled
519
+ product environment, restart policy, command, entrypoint, user, or health check
520
+ drifted, waits for management readiness, then creates and verifies the bucket
521
+ through an authenticated S3 client. A GitZone-label mismatch is an ownership
522
+ conflict and blocks mutation rather than being treated as repairable drift.
523
+ Container setup, management readiness, and the S3 operations share one deadline;
524
+ SmartBucket cleanup has its own bounded close. Docker mutations use the
525
+ container's immutable ID after exact-name discovery.
526
+ On failure, GitZone stops a pre-existing container only after that invocation's
527
+ start returned successfully. A newly created ID remains invocation-owned across
528
+ an uncertain start and can be stopped safely; an uncertain pre-existing start is
529
+ left adoptable rather than risking stopping another concurrent invocation. A
530
+ canonical container created but not yet started remains stopped for a safe retry.
531
+
532
+ ### Migrating legacy MinIO state
533
+
534
+ Persisted `minio` and `s3` service selections are rewritten to the canonical
535
+ `objectstorage` value. `S3_CONSOLE_PORT` is migrated to `S3_UI_PORT` when the
536
+ values do not conflict. The runtime migration also adds the separate admin
537
+ password and region fields and repairs only the exact invalid bucket name that
538
+ older GitZone versions generated. Legacy registry and data-marker entries are
539
+ retained as preserved migration evidence, not converted into active
540
+ ObjectStorage ownership. Every selected migration store is preflighted before
541
+ the first write. Closed-schema service selection, marker, and registry stores
542
+ reject malformed, conflicting, foreign, or future state without rewriting it.
543
+ Runtime config validates and migrates its known fields while preserving unknown
544
+ application fields.
545
+
546
+ If `<project>-minio`, a registry-retained alternate legacy container name, or
547
+ `.nogit/miniodata` still exists, ObjectStorage startup stops before mutating the
548
+ ObjectStorage container. In an untargeted `services start`, an earlier enabled
549
+ service such as MongoDB may already have started. GitZone never reuses, removes,
550
+ cleans, or prunes legacy MinIO state because its disk layout is not compatible
551
+ with ObjectStorage. Recovery is explicit:
552
+
553
+ 1. Export every required bucket with the existing MinIO tooling.
554
+ 2. Stop and rename the legacy container, then move `.nogit/miniodata` to a preserved backup location.
555
+ 3. Run `gitzone services start s3` to create the canonical service.
556
+ 4. Import through an external S3 client and verify the required objects before disposing of the backup.
557
+
558
+ An existing `.nogit/objectstoragedata` directory without a valid ownership
559
+ marker blocks creation of a new container and direct cleanup. One exception is
560
+ an existing container whose immutable identity and exact canonical GitZone
561
+ labels prove that directory belongs to this project; startup or removal repairs
562
+ the missing marker before proceeding. An invalid or foreign marker always
563
+ blocks mutation. Without that exact container proof, preserve or move the
564
+ directory, verify its provenance outside GitZone, start a fresh canonical
565
+ service, and import required objects through S3. Do not synthesize a marker for
566
+ unverified data.
496
567
 
497
568
  ### Consuming a service programmatically
498
569
 
@@ -503,6 +574,13 @@ script can read a live connection string without parsing human output:
503
574
  gitzone services status --json | jq -r '.services.mongodb.connectionString'
504
575
  ```
505
576
 
577
+ The ObjectStorage status key is `.services.objectstorage`; the former
578
+ `.services.minio` key no longer exists. Preserved predecessor evidence is
579
+ reported separately under `.legacy`. `minioDataDirectory` and `minioDataExists`
580
+ are always emitted; `minioContainer` is present only when container evidence
581
+ exists. Consumers must treat this as a breaking response-schema change rather
582
+ than interpreting legacy evidence as an active service.
583
+
506
584
  ### Cleanup levels
507
585
 
508
586
  Cleanup is tiered, from fully resumable to irreversible:
@@ -514,10 +592,26 @@ Cleanup is tiered, from fully resumable to irreversible:
514
592
  | `gitzone services clean` | removed | **removed** | irreversible; needs a typed `yes` or `--yes` |
515
593
  | `gitzone services prune` | see below | see below | machine-wide; dry run unless `--apply` |
516
594
 
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.
595
+ `clean` and `prune` first persist an exact deletion intent, then atomically rename
596
+ the canonical directory to a tokenized sibling quarantine before deleting any
597
+ contents. Native deletion is attempted there. If container-owned files remain,
598
+ GitZone uses a short-lived root container scoped to that quarantine; Docker's
599
+ `--privileged` mode is not used. The helper reserves one deterministic name per
600
+ bind target, carries a random invocation label, is created stopped, and is
601
+ inspected by immutable ID before execution or cleanup. Old stopped helpers can
602
+ be recovered only after their complete runtime envelope, bind target, age, and
603
+ immutable ID are proven; running, fresh, or noncanonical occupants block the
604
+ operation. If interruption or helper failure leaves bytes, the persisted intent
605
+ lets the next `clean` or `prune --apply` resume the same quarantine. A partial
606
+ failure therefore never leaves a corrupt directory at the canonical service
607
+ path. Startup refuses to create fresh service data while such an intent remains.
608
+
609
+ Service start, stop, container removal, and data removal share one interprocess
610
+ lock per project and service. Startup refreshes runtime config and project
611
+ activity inside that lock, while prune rechecks activity and stopped as well as
612
+ running service containers after acquiring it. Concurrent lifecycle commands
613
+ therefore serialize rather than deleting a directory or container while another
614
+ command prepares, mounts, starts, or stops it.
521
615
 
522
616
  ### Reclaiming space across projects
523
617
 
@@ -541,9 +635,18 @@ with: its directory is gone, or it has been inactive past the threshold with no
541
635
  container running. Anything ambiguous — an unlabeled container claimed by more
542
636
  than one project, an unreachable Docker daemon, a directory still mounted by a
543
637
  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.
638
+ are identified by an exact canonical GitZone label envelope. An unambiguous
639
+ registry claim is used only for older MongoDB and Elasticsearch containers with
640
+ no `git.zone.*` labels at all. ObjectStorage has no unlabeled predecessor
641
+ fallback; partial, missing, or conflicting GitZone labels fail closed. Removal
642
+ revalidates and uses the container's immutable ID, never its mutable name, so
643
+ pruning cannot touch a same-name replacement. If Docker becomes unavailable,
644
+ registry claims are preserved as well as containers and data.
645
+
646
+ Legacy MinIO containers and registry references are reported as preserved
647
+ migration resources and are never prune candidates. `.nogit/miniodata` is
648
+ deliberately outside the prune allowlist; current-project `status` reports its
649
+ presence, while machine-wide prune leaves it untouched.
547
650
 
548
651
  ### MongoDB authentication
549
652
 
@@ -608,11 +711,11 @@ make it look like an older version is installed when it is not:
608
711
 
609
712
  ```bash
610
713
  gitzone --version
611
- # 2.25.0
612
- # resolved from: /home/you/.local/share/pnpm/store/v11/links/@git.zone/cli/2.25.0/…
714
+ # 3.2.1
715
+ # resolved from: /home/you/.local/share/pnpm/store/v11/links/@git.zone/cli/3.2.1/…
613
716
 
614
717
  gitzone --version --json
615
- # {"version":"2.25.0","resolvedFrom":"…"}
718
+ # {"version":"3.2.1","resolvedFrom":"…"}
616
719
  ```
617
720
 
618
721
  `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.1',
6
+ version: '5.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
  }