@styleflow.app/flowpress-deploy 1.0.0-beta.3 → 1.0.0-beta.31

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 (175) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/README.md +5 -0
  3. package/composer.json +1 -1
  4. package/containers/cms/Dockerfile +35 -0
  5. package/containers/cms/Dockerfile.dockerignore +20 -0
  6. package/containers/cms/healthz.php +17 -0
  7. package/containers/cms/install-languages.sh +16 -0
  8. package/containers/cms/mpm.conf +10 -0
  9. package/containers/cms/php.ini +16 -0
  10. package/containers/cms/sanitize-integrations.php +14 -0
  11. package/containers/cms/sanitize.php +40 -0
  12. package/containers/cms/smtp.php +13 -0
  13. package/containers/cms/vhost.conf +61 -0
  14. package/containers/cms/wp-cli.yml +1 -0
  15. package/containers/local/cms/Dockerfile +18 -0
  16. package/containers/local/cms/entrypoint.sh +7 -0
  17. package/containers/local/cms/php.ini +8 -0
  18. package/containers/local/cms/vhost.conf +14 -0
  19. package/containers/local/runtimes.json +14 -0
  20. package/containers/local/web/Dockerfile +8 -0
  21. package/containers/local/web/entrypoint.sh +21 -0
  22. package/containers/php-runtime/Dockerfile +21 -0
  23. package/containers/web-ssr/Dockerfile +27 -0
  24. package/containers/web-ssr/Dockerfile.dockerignore +10 -0
  25. package/containers/web-static/Caddyfile +40 -0
  26. package/containers/web-static/Dockerfile +17 -0
  27. package/containers/web-static/Dockerfile.dockerignore +7 -0
  28. package/dist/development.d.ts +12 -0
  29. package/dist/development.d.ts.map +1 -0
  30. package/dist/development.js +57 -0
  31. package/dist/development.js.map +1 -0
  32. package/dist/node-fetch.d.ts +3 -0
  33. package/dist/node-fetch.d.ts.map +1 -0
  34. package/dist/node-fetch.js +20 -0
  35. package/dist/node-fetch.js.map +1 -0
  36. package/dist/ops/bootstrap.d.ts +24 -0
  37. package/dist/ops/bootstrap.d.ts.map +1 -0
  38. package/dist/ops/bootstrap.js +156 -0
  39. package/dist/ops/bootstrap.js.map +1 -0
  40. package/dist/ops/build.d.ts +45 -0
  41. package/dist/ops/build.d.ts.map +1 -0
  42. package/dist/ops/build.js +119 -0
  43. package/dist/ops/build.js.map +1 -0
  44. package/dist/ops/check.d.ts +14 -0
  45. package/dist/ops/check.d.ts.map +1 -0
  46. package/dist/ops/check.js +42 -0
  47. package/dist/ops/check.js.map +1 -0
  48. package/dist/ops/cli.d.ts +3 -0
  49. package/dist/ops/cli.d.ts.map +1 -0
  50. package/dist/ops/cli.js +198 -0
  51. package/dist/ops/cli.js.map +1 -0
  52. package/dist/ops/cms-migrate.d.ts +14 -0
  53. package/dist/ops/cms-migrate.d.ts.map +1 -0
  54. package/dist/ops/cms-migrate.js +133 -0
  55. package/dist/ops/cms-migrate.js.map +1 -0
  56. package/dist/ops/cms-template/command.d.mts +19 -0
  57. package/dist/ops/cms-template/command.d.mts.map +1 -0
  58. package/dist/ops/cms-template/command.mjs +145 -0
  59. package/dist/ops/cms-template/command.mjs.map +1 -0
  60. package/dist/ops/cms-template/confirm.d.mts +11 -0
  61. package/dist/ops/cms-template/confirm.d.mts.map +1 -0
  62. package/dist/ops/cms-template/confirm.mjs +18 -0
  63. package/dist/ops/cms-template/confirm.mjs.map +1 -0
  64. package/dist/ops/cms-template/entry.d.mts +2 -0
  65. package/dist/ops/cms-template/entry.d.mts.map +1 -0
  66. package/dist/ops/cms-template/entry.mjs +22 -0
  67. package/dist/ops/cms-template/entry.mjs.map +1 -0
  68. package/dist/ops/cms-template/git.d.mts +7 -0
  69. package/dist/ops/cms-template/git.d.mts.map +1 -0
  70. package/dist/ops/cms-template/git.mjs +22 -0
  71. package/dist/ops/cms-template/git.mjs.map +1 -0
  72. package/dist/ops/cms-template/plan.d.mts +7 -0
  73. package/dist/ops/cms-template/plan.d.mts.map +1 -0
  74. package/dist/ops/cms-template/plan.mjs +54 -0
  75. package/dist/ops/cms-template/plan.mjs.map +1 -0
  76. package/dist/ops/cms-template/store.d.mts +21 -0
  77. package/dist/ops/cms-template/store.d.mts.map +1 -0
  78. package/dist/ops/cms-template/store.mjs +184 -0
  79. package/dist/ops/cms-template/store.mjs.map +1 -0
  80. package/dist/ops/cms-template/target.d.mts +15 -0
  81. package/dist/ops/cms-template/target.d.mts.map +1 -0
  82. package/dist/ops/cms-template/target.mjs +24 -0
  83. package/dist/ops/cms-template/target.mjs.map +1 -0
  84. package/dist/ops/cms-template/transport.d.mts +26 -0
  85. package/dist/ops/cms-template/transport.d.mts.map +1 -0
  86. package/dist/ops/cms-template/transport.mjs +115 -0
  87. package/dist/ops/cms-template/transport.mjs.map +1 -0
  88. package/dist/ops/config.d.ts +54 -0
  89. package/dist/ops/config.d.ts.map +1 -0
  90. package/dist/ops/config.js +221 -0
  91. package/dist/ops/config.js.map +1 -0
  92. package/dist/ops/coolify.d.ts +2 -0
  93. package/dist/ops/coolify.d.ts.map +1 -0
  94. package/dist/ops/coolify.js +44 -0
  95. package/dist/ops/coolify.js.map +1 -0
  96. package/dist/ops/data.d.ts +31 -0
  97. package/dist/ops/data.d.ts.map +1 -0
  98. package/dist/ops/data.js +165 -0
  99. package/dist/ops/data.js.map +1 -0
  100. package/dist/ops/deploy.d.ts +38 -0
  101. package/dist/ops/deploy.d.ts.map +1 -0
  102. package/dist/ops/deploy.js +127 -0
  103. package/dist/ops/deploy.js.map +1 -0
  104. package/dist/ops/editorial.d.ts +23 -0
  105. package/dist/ops/editorial.d.ts.map +1 -0
  106. package/dist/ops/editorial.js +79 -0
  107. package/dist/ops/editorial.js.map +1 -0
  108. package/dist/ops/environment-files.d.ts +9 -0
  109. package/dist/ops/environment-files.d.ts.map +1 -0
  110. package/dist/ops/environment-files.js +127 -0
  111. package/dist/ops/environment-files.js.map +1 -0
  112. package/dist/ops/environment.d.ts +31 -0
  113. package/dist/ops/environment.d.ts.map +1 -0
  114. package/dist/ops/environment.js +165 -0
  115. package/dist/ops/environment.js.map +1 -0
  116. package/dist/ops/features.d.ts +12 -0
  117. package/dist/ops/features.d.ts.map +1 -0
  118. package/dist/ops/features.js +71 -0
  119. package/dist/ops/features.js.map +1 -0
  120. package/dist/ops/health.d.ts +26 -0
  121. package/dist/ops/health.d.ts.map +1 -0
  122. package/dist/ops/health.js +27 -0
  123. package/dist/ops/health.js.map +1 -0
  124. package/dist/ops/local.d.ts +198 -0
  125. package/dist/ops/local.d.ts.map +1 -0
  126. package/dist/ops/local.js +187 -0
  127. package/dist/ops/local.js.map +1 -0
  128. package/dist/ops/media-config.d.ts +61 -0
  129. package/dist/ops/media-config.d.ts.map +1 -0
  130. package/dist/ops/media-config.js +96 -0
  131. package/dist/ops/media-config.js.map +1 -0
  132. package/dist/ops/media.d.ts +47 -0
  133. package/dist/ops/media.d.ts.map +1 -0
  134. package/dist/ops/media.js +81 -0
  135. package/dist/ops/media.js.map +1 -0
  136. package/dist/ops/monitor.d.ts +25 -0
  137. package/dist/ops/monitor.d.ts.map +1 -0
  138. package/dist/ops/monitor.js +143 -0
  139. package/dist/ops/monitor.js.map +1 -0
  140. package/dist/ops/process.d.ts +9 -0
  141. package/dist/ops/process.d.ts.map +1 -0
  142. package/dist/ops/process.js +56 -0
  143. package/dist/ops/process.js.map +1 -0
  144. package/dist/ops/provision.d.ts +41 -0
  145. package/dist/ops/provision.d.ts.map +1 -0
  146. package/dist/ops/provision.js +268 -0
  147. package/dist/ops/provision.js.map +1 -0
  148. package/dist/ops/registry.d.ts +14 -0
  149. package/dist/ops/registry.d.ts.map +1 -0
  150. package/dist/ops/registry.js +112 -0
  151. package/dist/ops/registry.js.map +1 -0
  152. package/dist/ops/release.d.ts +26 -0
  153. package/dist/ops/release.d.ts.map +1 -0
  154. package/dist/ops/release.js +79 -0
  155. package/dist/ops/release.js.map +1 -0
  156. package/dist/ops/runtimes.d.ts +16 -0
  157. package/dist/ops/runtimes.d.ts.map +1 -0
  158. package/dist/ops/runtimes.js +70 -0
  159. package/dist/ops/runtimes.js.map +1 -0
  160. package/dist/ops/s3.d.ts +8 -0
  161. package/dist/ops/s3.d.ts.map +1 -0
  162. package/dist/ops/s3.js +38 -0
  163. package/dist/ops/s3.js.map +1 -0
  164. package/dist/ops/static-config.d.ts +14 -0
  165. package/dist/ops/static-config.d.ts.map +1 -0
  166. package/dist/ops/static-config.js +92 -0
  167. package/dist/ops/static-config.js.map +1 -0
  168. package/dist/ops/storage.d.ts +39 -0
  169. package/dist/ops/storage.d.ts.map +1 -0
  170. package/dist/ops/storage.js +108 -0
  171. package/dist/ops/storage.js.map +1 -0
  172. package/flowpress-deploy.php +2 -2
  173. package/includes/pilot-aliases.php +69 -0
  174. package/package.json +43 -6
  175. package/schema/deployment.schema.json +306 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,167 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0-beta.31 — 2026-10-21
4
+
5
+ - Conserva le credenziali native nei profili privati anche quando lo storage locale è selezionato; gli esempi e il runtime continuano a escludere i segreti non pertinenti.
6
+ - Richiede Core beta.39 e ne verifica la protezione delle pulizie automatiche prima di dichiarare sano lo storage condiviso. Include il contratto TypeScript corretto di beta.30.
7
+ - [Rapporto canonico](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-21-storage-condiviso-manuale-flowpress.md).
8
+
9
+ ## 1.0.0-beta.30 — 2026-10-21
10
+
11
+ - Mantiene il contratto TypeScript `Record<string, string>` degli ambienti dopo il filtraggio delle credenziali media; verifica le dichiarazioni pubblicate con un consumer TypeScript. Corregge beta.29 prima dell’adozione DMO.
12
+ - [Rapporto canonico](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-21-storage-condiviso-manuale-flowpress.md).
13
+
14
+ ## 1.0.0-beta.29 — 2026-10-21
15
+
16
+ - Importazioni condivise conservano metadati e percorsi soltanto con namespace sorgente/destinazione verificato; nessuna credenziale media nel container di trasformazione DB.
17
+ - Manifest media v2 per sei provider, override ambientali completi e lettura dei manifest v1.
18
+ - Migrazione esplicita con anteprima e copia privata; credenziali native soltanto nel CMS e verifica di coerenza degli URL.
19
+ - Comandi `media status` e `media check` senza scritture sul bucket e senza valori segreti; richiede Core beta.38.
20
+ - [Rapporto canonico](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-21-storage-condiviso-manuale-flowpress.md).
21
+
22
+ ## 1.0.0-beta.28
23
+
24
+ - Verify restored local backups against the persisted database home when WP_HOME is overridden by the environment. Active CMS identity remains checked separately before planning and applying.
25
+
26
+
27
+ ## 1.0.0-beta.27 — 2026-10-20
28
+
29
+ - Use WP-CLI `eval-file -` for stdin migration programs; /dev/stdin is not readable in the DMO container.
30
+ - Exercise the exact stdin program through real WP-CLI before publication.
31
+ - Keep the protocol status output concise.
32
+ - [Canonical report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-20-sync-site-editor-ritiro-legacy.md).
33
+
34
+ ## 1.0.0-beta.26 — 2026-10-20
35
+
36
+ - Correct Linux ownership cleanup in the WordPress migration integration fixture; beta.25 tag failed CI before publication and remains immutable.
37
+ - Own Site Editor sync protocol 1, manifest-aware targets, feature operations and explicit backed-up pilot-alias migrations.
38
+ - Retire the Scaffold dependency in operational checks and share development helpers.
39
+ - [Canonical report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-20-sync-site-editor-ritiro-legacy.md).
40
+
41
+ ## 1.0.0-beta.24
42
+
43
+ - Keep local clean --apply --json machine-readable by capturing Docker removal output. Verify the real CLI JSON response against Docker fixtures.
44
+
45
+ ## 1.0.0-beta.23
46
+
47
+ - Share digest-pinned native CMS and web runtimes across local projects, built once in CI for ARM64/AMD64 and verified before npm publication.
48
+ - Add read-only local storage inventory and explicit image cleanup with container/reference protection; preserve volumes and global caches.
49
+ - Require --push or --load for deployment image builds; stop implicit AMD64 image loading on development machines.
50
+
51
+ ## 1.0.0-beta.22
52
+
53
+ - Preserve stdout from local exec and streaming commands so maintenance tools can consume WP-CLI JSON without CLI status text.
54
+
55
+ ## 1.0.0-beta.21
56
+
57
+ - Preserve shell variables through Compose interpolation and use a variable-free PHP readiness probe. Verify the generated Compose configuration and probe syntax through the real CLI.
58
+ - Isolate CMS workspace dependencies and Vite caches in Docker volumes, start the StyleFlow build/watch cycle, and allow the initial Astro compilation to complete before declaring the frontend unhealthy.
59
+
60
+ ## 1.0.0-beta.20
61
+
62
+ - Correct the local Apache Options directive and validate the development vhost with the real Apache server in the release gate.
63
+
64
+ ## 1.0.0-beta.19
65
+
66
+ - Centralize full local development in flowpress-ops: profile-driven database, WordPress, hot-reload Astro and trusted HTTPS containers; preserve existing database volumes.
67
+ - Keep Docker recipes in the package and generated runtime under ignored .local. Expose local start/stop/status/logs/exec/backup/datagrip commands.
68
+ - Separate public HTTPS origins from internal development ports in the manifest.
69
+
70
+ ## 1.0.0-beta.18
71
+
72
+ - Serialize JSON environment settings with native dotenv quoting so Node and PHP read valid frontend registries. Preserve unchanged private assignments verbatim.
73
+
74
+ ## 1.0.0-beta.17
75
+
76
+ - Synchronize all four environment files and examples from the deployment manifest, preserving each environment’s private settings with protected backups. Retire legacy dev and provider variables.
77
+ - Prepare cached development safelists without a remote CMS scan; strict builds still regenerate content classes.
78
+ - Resolve explicit media origins from the selected backend, including production-backed previews.
79
+
80
+ ## 1.0.0-beta.16
81
+
82
+ - Remove all persisted offload, SMTP and migration connection options from non-production clones; expose explicit integration cleanup for existing clones.
83
+ - Align the JSON schema with supported backend aliases.
84
+
85
+ ## 1.0.0-beta.15
86
+
87
+ - Export a Node fetch adapter for media proxies: negotiate identity encoding and remove encoding metadata after automatic decompression.
88
+ - Verify gzip proxying against a real HTTP server.
89
+
90
+ ## 1.0.0-beta.14
91
+
92
+ - Preserve provider timestamp offsets when waiting for backup completion.
93
+ - Report WordPress staging as staging in the administration interface.
94
+ - Remove disposable restore volumes after backup verification.
95
+
96
+ ## 1.0.0-beta.13
97
+
98
+ - Remove disposable database volumes together with their test and transformation containers.
99
+
100
+ - Activate the shared database only for installations that publish a CMS; frontend-only and preview-only profiles need no database engine.
101
+ - Keep deployment history out of committed provider bindings, with a private local journal and authoritative registry metadata.
102
+
103
+
104
+ ## 1.0.0-beta.12
105
+
106
+ - Keep CI on Coolify read/deploy permissions using verified environment image aliases. Derive current, rollback and promotion records from registry metadata instead of stale runner state. Provision frontend environment separately and bake SSR build identity into the image.
107
+
108
+ - Make the sanitization script executable by WP-CLI eval-file and verify its production barrier with the real CLI.
109
+ - Include WordPress GraphQL in CMS release health; optionally save command diagnostics in a private operator file.
110
+
111
+
112
+ ## 1.0.0-beta.11
113
+
114
+ - Resolve platform server and panel references from the canonical infrastructure inventory.
115
+ - Reuse an existing CMS image by commit SHA; refuse ambiguous registry failures instead of overwriting a release.
116
+ - Verify status against the image configured in Coolify after CI deployments.
117
+
118
+
119
+ ## 1.0.0-beta.10
120
+
121
+ - Keep local HTTP origins out of remote WordPress frontend registries.
122
+ - Read the shared engine administrator secret from the operator configuration; never silently replace a missing pool password.
123
+
124
+
125
+ ## 1.0.0-beta.9
126
+
127
+ - Keep editorial pages under /media/ available in static deployments; proxy only media files. Verify the behavior against a real Caddy runtime.
128
+
129
+
130
+ ## 1.0.0-beta.8
131
+
132
+ - Exclude private backup files from media snapshots and reject them before uploads. Deny HTTP access to SQL dumps and migration backup directories.
133
+ - Preserve existing schema backup bindings across repeated provisioning.
134
+
135
+
136
+ ## 1.0.0-beta.7
137
+
138
+ - Preserve the local backend selection and explicit environment overrides used by isolated build fixtures. Stored environment URLs still defer to the manifest.
139
+
140
+
141
+ ## 1.0.0-beta.6
142
+
143
+ - Encode MariaDB configuration for the Coolify API and preserve robot level when extending Harbor pull permissions.
144
+ - Retain current and previous deployment aliases without changing immutable release tags.
145
+
146
+
147
+ ## 1.0.0-beta.5 — 2026-10-19
148
+
149
+ - Use individually scoped system robots for repeatable Harbor provisioning; pass content build IDs to SSR health checks.
150
+ - [Canonical report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-19-piattaforma-container-flowpress.md).
151
+
152
+ ## 1.0.0-beta.4 — 2026-10-19
153
+
154
+ - Add published FlowPress Ops CLI, readable deployment manifests, shared MariaDB bindings, reusable container runtimes, isolated environment loading, immutable releases, backup verification and on-demand preview.
155
+ - [Canonical report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-19-piattaforma-container-flowpress.md).
156
+
157
+ ## Unreleased
158
+
159
+ - Agent rules only, no runtime or API change: `AGENTS.md` names the canonical
160
+ docs vault path (2026-10-18) and requires every published change to be
161
+ merged into `main`, with its branches, worktrees and stashes removed in the
162
+ same task.
163
+ [Canonical report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-19-branch-residui-e-regole-di-chiusura.md).
164
+
3
165
  ## 1.0.0-beta.3 — 2026-10-14
4
166
 
5
167
  - Queue complete builds for term-only changes to published content, including withdrawal after a visibility change. Keep unchanged assignments idle and avoid private data in the queue.
package/README.md CHANGED
@@ -4,3 +4,8 @@ Official npm/Composer integration for FlowPress.
4
4
 
5
5
  - [Canonical guide](https://github.com/StyleFlow-App/styleflow-docs/blob/main/wiki/flowpress-routing-deploy.md)
6
6
  - [Release and verification report](https://github.com/StyleFlow-App/styleflow-docs/blob/main/dev/rapporti/2026-10-14-consolidamento-tessari.md)
7
+
8
+ - [Container platform and FlowPress Ops](https://github.com/StyleFlow-App/styleflow-docs/blob/main/wiki/piattaforma-container-flowpress.md)
9
+
10
+ The npm package also provides the flowpress-ops binary, reusable container
11
+ recipes and the ./ops/environment API. Run flowpress-ops --help for commands.
package/composer.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "license": "proprietary",
6
6
  "require": {
7
7
  "php": ">=8.1",
8
- "flowpress/wordpress-core": "^1.0.0@beta"
8
+ "flowpress/wordpress-core": "^1.0.0-beta.39"
9
9
  },
10
10
  "extra": {"installer-name": "flowpress-deploy"}
11
11
  }
@@ -0,0 +1,35 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ # The reusable PHP runtime is built once by platform build-base.
3
+ ARG FLOWPRESS_PHP_IMAGE
4
+ FROM $FLOWPRESS_PHP_IMAGE AS build
5
+ USER root
6
+ RUN apt-get update && apt-get install -y --no-install-recommends git && rm -rf /var/lib/apt/lists/*
7
+ COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer
8
+ WORKDIR /srv/cms
9
+ COPY apps/cms/ ./
10
+ RUN --mount=type=secret,id=composer_auth,required=true \
11
+ --mount=type=cache,target=/root/.composer/cache \
12
+ COMPOSER_AUTH="$(cat /run/secrets/composer_auth)" \
13
+ composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-progress
14
+ COPY --from=flowpress /cms/install-languages.sh /usr/local/bin/install-languages
15
+ RUN sh /usr/local/bin/install-languages /srv/cms/web
16
+ ARG WP_CLI_VERSION=2.12.0
17
+ ARG WP_CLI_SHA256=ce34ddd838f7351d6759068d09793f26755463b4a4610a5a5c0a97b68220d85c
18
+ RUN curl -fsSL "https://github.com/wp-cli/wp-cli/releases/download/v$WP_CLI_VERSION/wp-cli-$WP_CLI_VERSION.phar" -o /wp-cli.phar \
19
+ && echo "$WP_CLI_SHA256 /wp-cli.phar" | sha256sum -c - && chmod 755 /wp-cli.phar
20
+ FROM $FLOWPRESS_PHP_IMAGE
21
+ WORKDIR /srv/cms
22
+ COPY --from=build /srv/cms/ ./
23
+ COPY --from=build /wp-cli.phar /usr/local/bin/wp
24
+ COPY --from=flowpress /cms/wp-cli.yml /srv/cms/wp-cli.yml
25
+ COPY --from=flowpress /cms/healthz.php /srv/cms/web/healthz.php
26
+ COPY --from=flowpress /cms/smtp.php /usr/local/share/flowpress-smtp.php
27
+ RUN mkdir -p web/app/uploads web/app/webp-express web/app/cache web/app/upgrade \
28
+ && chown -R www-data:www-data web/app/uploads web/app/webp-express web/app/cache web/app/upgrade \
29
+ && echo 'auto_prepend_file=/usr/local/share/flowpress-smtp.php' > /usr/local/etc/php/conf.d/zz-smtp.ini
30
+ ARG RELEASE_SHA=unknown
31
+ ENV RELEASE_SHA=$RELEASE_SHA
32
+ LABEL org.opencontainers.image.revision=$RELEASE_SHA
33
+ USER www-data
34
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=5 CMD curl -fsS http://127.0.0.1:8080/healthz.php > /dev/null || exit 1
35
+ CMD ["apache2-foreground"]
@@ -0,0 +1,20 @@
1
+ .git
2
+ node_modules
3
+ .env*
4
+ .secrets
5
+ .local
6
+ .styleflow
7
+ apps/web
8
+ packages
9
+ docs
10
+ apps/cms/vendor
11
+ apps/cms/auth.json
12
+ apps/cms/.env*
13
+ apps/cms/web/wp
14
+ apps/cms/web/app/plugins
15
+ apps/cms/web/app/uploads
16
+ apps/cms/web/app/webp-express
17
+ apps/cms/web/app/cache
18
+ apps/cms/web/app/upgrade
19
+ apps/cms/web/app/mu-plugins/flowpress-*
20
+ apps/cms/web/app/mu-plugins/flowpress-core
@@ -0,0 +1,17 @@
1
+ <?php
2
+ declare(strict_types=1);
3
+ header('Content-Type: application/json');
4
+ header('Cache-Control: no-store');
5
+ try {
6
+ define('SHORTINIT', true);
7
+ require __DIR__ . '/wp/wp-load.php';
8
+ global $wpdb;
9
+ $installed = $wpdb->get_var("SELECT option_value FROM {$wpdb->options} WHERE option_name = 'siteurl'");
10
+ if (!$installed || !is_readable(__DIR__ . '/app/mu-plugins/flowpress-core/flowpress-core.php')) {
11
+ throw new RuntimeException('CMS not initialized.');
12
+ }
13
+ echo json_encode(['status' => 'ok', 'environment' => getenv('APP_ENV'), 'release' => getenv('RELEASE_SHA')]);
14
+ } catch (Throwable $error) {
15
+ http_response_code(503);
16
+ echo json_encode(['status' => 'error', 'release' => getenv('RELEASE_SHA')]);
17
+ }
@@ -0,0 +1,16 @@
1
+ #!/bin/sh
2
+ # Installs the Italian WordPress core translation matching the installed core.
3
+ # Languages are gitignored and DISALLOW_FILE_MODS blocks installing them at
4
+ # runtime, so they are part of the image.
5
+ set -eu
6
+ web_root="$1"
7
+ version="$(php -r "include '$web_root/wp/wp-includes/version.php'; echo \$wp_version;")"
8
+ package="$(curl -fsSL "https://api.wordpress.org/translations/core/1.0/?version=$version" \
9
+ | php -r '$d = json_decode(stream_get_contents(STDIN), true);
10
+ foreach ($d["translations"] ?? [] as $t) { if ($t["language"] === "it_IT") { echo $t["package"]; exit; } }
11
+ exit(1);')"
12
+ mkdir -p "$web_root/app/languages"
13
+ curl -fsSL "$package" -o /tmp/it_IT.zip
14
+ unzip -oq /tmp/it_IT.zip -d "$web_root/app/languages"
15
+ rm /tmp/it_IT.zip
16
+ echo "Installed it_IT core translation for WordPress $version."
@@ -0,0 +1,10 @@
1
+ # Sized for a 1536m container limit: 8 workers at up to 256M PHP memory each,
2
+ # typical WordPress requests use far less.
3
+ <IfModule mpm_prefork_module>
4
+ StartServers 2
5
+ MinSpareServers 2
6
+ MaxSpareServers 4
7
+ ServerLimit 8
8
+ MaxRequestWorkers 8
9
+ MaxConnectionsPerChild 500
10
+ </IfModule>
@@ -0,0 +1,16 @@
1
+ expose_php = Off
2
+ display_errors = Off
3
+ log_errors = On
4
+ error_log = /proc/self/fd/2
5
+ memory_limit = 256M
6
+ upload_max_filesize = 64M
7
+ post_max_size = 68M
8
+ max_execution_time = 120
9
+ max_input_vars = 3000
10
+ session.save_path = /tmp
11
+ ; Code is immutable inside the image: never stat files for changes.
12
+ opcache.enable = 1
13
+ opcache.validate_timestamps = 0
14
+ opcache.memory_consumption = 128
15
+ opcache.interned_strings_buffer = 16
16
+ opcache.max_accelerated_files = 20000
@@ -0,0 +1,14 @@
1
+ <?php
2
+ if (getenv('FLOWPRESS_RUNTIME_POLICY') !== 'container' || getenv('APP_ENV') === 'production') {
3
+ throw new RuntimeException('Refusing to clean integrations in production.');
4
+ }
5
+ global $wpdb;
6
+ $removed = 0;
7
+ foreach ($wpdb->get_col("SELECT option_name FROM {$wpdb->options}") as $name) {
8
+ if (preg_match('/^(advmo_|wp_mail_smtp|wpmdb_|wp_migrate_)/', $name)) {
9
+ if (delete_option($name)) {
10
+ $removed++;
11
+ }
12
+ }
13
+ }
14
+ echo json_encode(['integrationOptionsRemoved' => $removed]) . "\n";
@@ -0,0 +1,40 @@
1
+ <?php
2
+ // Executed only against a disposable copy, never against the source.
3
+ if (getenv('FLOWPRESS_RUNTIME_POLICY') !== 'container' || getenv('APP_ENV') === 'production') {
4
+ throw new RuntimeException('Refusing to sanitize a production database.');
5
+ }
6
+ global $wpdb;
7
+ foreach (get_users(['fields' => 'ID']) as $user_id) {
8
+ $wpdb->update($wpdb->users, ['user_pass' => wp_hash_password(wp_generate_password(64, true, true)), 'user_activation_key' => ''], ['ID' => $user_id]);
9
+ delete_user_meta((int) $user_id, 'session_tokens');
10
+ delete_user_meta((int) $user_id, '_application_passwords');
11
+ }
12
+ $plugins = get_option('active_plugins', []);
13
+ update_option('active_plugins', array_values(array_filter($plugins, static fn (string $plugin): bool
14
+ => !preg_match('~^(advanced-media-offloader|wp-mail-smtp|wp-migrate-db-pro)/~', $plugin))));
15
+ require __DIR__ . '/sanitize-integrations.php';
16
+ foreach (['cron'] as $option) {
17
+ delete_option($option);
18
+ }
19
+ update_option('home', getenv('WP_HOME'));
20
+ update_option('siteurl', getenv('WP_SITEURL'));
21
+ update_option('blog_public', '0');
22
+ $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'flowpress%queue%' OR option_name LIKE '%_transient_%'");
23
+ $attachments = get_posts(['post_type' => 'attachment', 'post_status' => 'any', 'numberposts' => -1, 'fields' => 'ids']);
24
+ foreach ($attachments as $id) {
25
+ // Shared cloud paths belong to both databases. Never rewrite existing keys.
26
+ if (getenv('FLOWPRESS_MEDIA_IMPORT_PRESERVE') === 'true') continue;
27
+ $relative = get_post_meta($id, '_wp_attached_file', true);
28
+ if (is_string($relative) && $relative !== '' && !str_contains($relative, '..') && !str_contains($relative, '://')) {
29
+ $wpdb->update($wpdb->posts, ['guid' => rtrim(getenv('WP_HOME'), '/') . '/app/uploads/' . ltrim($relative, '/')], ['ID' => $id]);
30
+ clean_post_cache($id);
31
+ }
32
+ foreach (array_keys(get_post_meta($id)) as $key) {
33
+ if (preg_match('/advmo|offload/i', $key)) delete_post_meta($id, $key);
34
+ }
35
+ }
36
+ echo json_encode([
37
+ 'tables' => count($wpdb->get_col($wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($wpdb->prefix) . '%'))),
38
+ 'published' => (int) $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_status='publish'"),
39
+ 'attachments' => count($attachments),
40
+ ]) . "\n";
@@ -0,0 +1,13 @@
1
+ <?php
2
+ // Runs before Bedrock without reading any project file or persisted option.
3
+ if (getenv('FLOWPRESS_RUNTIME_POLICY') === 'container' && getenv('FLOWPRESS_MAIL_MODE') === 'smtp' && getenv('APP_ENV') === 'production') {
4
+ foreach ([
5
+ 'WPMS_ON' => true, 'WPMS_MAILER' => 'smtp',
6
+ 'WPMS_SMTP_HOST' => getenv('SMTP_HOST'), 'WPMS_SMTP_PORT' => (int) getenv('SMTP_PORT'),
7
+ 'WPMS_SMTP_SSL' => getenv('SMTP_ENCRYPTION'), 'WPMS_SMTP_AUTH' => true,
8
+ 'WPMS_SMTP_USER' => getenv('SMTP_USER'), 'WPMS_SMTP_PASS' => getenv('SMTP_PASSWORD'),
9
+ 'WPMS_MAIL_FROM' => getenv('SMTP_FROM'), 'WPMS_MAIL_FROM_NAME' => getenv('SMTP_FROM_NAME'),
10
+ ] as $key => $value) {
11
+ if (!defined($key)) define($key, $value);
12
+ }
13
+ }
@@ -0,0 +1,61 @@
1
+ # Apache vhost for the container CMS. .htaccess files are ignored
2
+ # (AllowOverride None): every rule WordPress needs is declared here.
3
+ <VirtualHost *:8080>
4
+ ServerName localhost
5
+ DocumentRoot /srv/cms/web
6
+
7
+ <Directory /srv/cms/web>
8
+ AllowOverride None
9
+ Options +FollowSymLinks -Indexes
10
+ Require all granted
11
+ DirectoryIndex index.php
12
+
13
+ RewriteEngine On
14
+ # Application Passwords (cms:template) and Bearer callbacks need the
15
+ # Authorization header inside PHP.
16
+ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
17
+ RewriteRule ^index\.php$ - [L]
18
+ RewriteCond %{REQUEST_FILENAME} !-f
19
+ RewriteCond %{REQUEST_FILENAME} !-d
20
+ RewriteRule . /index.php [L]
21
+ </Directory>
22
+
23
+ # Uploaded files are data, never code.
24
+ <Directory /srv/cms/web/app/uploads>
25
+ <FilesMatch "(?i)\.(php[0-9]?|phtml|phar|pht|sql|sql\.gz|env|bak)$">
26
+ Require all denied
27
+ </FilesMatch>
28
+ </Directory>
29
+ <Directory /srv/cms/web/app/uploads/wp-migrate-db>
30
+ Require all denied
31
+ </Directory>
32
+ <FilesMatch "^\.|^(auth\.json|composer\.(json|lock)|wp-cli\.yml)$">
33
+ Require all denied
34
+ </FilesMatch>
35
+ <Files "xmlrpc.php">
36
+ Require all denied
37
+ </Files>
38
+
39
+ # Traefik (Docker network) sits in front; Cloudflare adds CF-Connecting-IP.
40
+ # Only the private proxy hop is trusted, see docs/wiki/deploy/07-sicurezza-e-accessi.md.
41
+ RemoteIPHeader CF-Connecting-IP
42
+ RemoteIPInternalProxy 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
43
+ SetEnvIfNoCase X-Forwarded-Proto "^https$" HTTPS=on
44
+
45
+ <IfModule mod_expires.c>
46
+ ExpiresActive On
47
+ ExpiresByType image/webp "access plus 30 days"
48
+ ExpiresByType image/avif "access plus 30 days"
49
+ ExpiresByType image/jpeg "access plus 30 days"
50
+ ExpiresByType image/png "access plus 30 days"
51
+ ExpiresByType image/svg+xml "access plus 30 days"
52
+ ExpiresByType font/woff2 "access plus 1 year"
53
+ </IfModule>
54
+
55
+ Header always set X-Content-Type-Options "nosniff"
56
+ Header always set Referrer-Policy "strict-origin-when-cross-origin"
57
+
58
+ LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" container
59
+ ErrorLog /proc/self/fd/2
60
+ CustomLog /proc/self/fd/1 container
61
+ </VirtualHost>
@@ -0,0 +1 @@
1
+ path: web/wp
@@ -0,0 +1,18 @@
1
+ FROM php:8.3-apache@sha256:f8506a19d79cad7fcf0c8049f1ed2208824961018fdc10bd80f324094dcd36bd
2
+ RUN apt-get update \
3
+ && apt-get install -y --no-install-recommends \
4
+ ca-certificates default-mysql-client libicu-dev libjpeg62-turbo-dev \
5
+ libpng-dev libwebp-dev libzip-dev unzip webp \
6
+ && docker-php-ext-configure gd --with-jpeg --with-webp \
7
+ && docker-php-ext-install gd mysqli pdo_mysql intl opcache \
8
+ && a2enmod rewrite headers expires remoteip \
9
+ && echo "ServerName localhost" > /etc/apache2/conf-available/servername.conf \
10
+ && a2enconf servername \
11
+ && rm -rf /var/lib/apt/lists/*
12
+ COPY local/cms/vhost.conf /etc/apache2/sites-available/000-default.conf
13
+ COPY local/cms/php.ini /usr/local/etc/php/conf.d/zz-local.ini
14
+ COPY local/cms/entrypoint.sh /usr/local/bin/flowpress-local-cms
15
+ RUN chmod 755 /usr/local/bin/flowpress-local-cms
16
+ WORKDIR /workspace/apps/cms/web
17
+ ENTRYPOINT ["flowpress-local-cms"]
18
+ CMD ["apache2-foreground"]
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ if [ -r /certs/local-dev-root-ca.pem ]; then
4
+ cp /certs/local-dev-root-ca.pem /usr/local/share/ca-certificates/flowpress-local.crt
5
+ update-ca-certificates >/dev/null
6
+ fi
7
+ exec docker-php-entrypoint "$@"
@@ -0,0 +1,8 @@
1
+ upload_max_filesize = 128M
2
+ post_max_size = 128M
3
+ max_file_uploads = 200
4
+ max_execution_time = 120
5
+ display_errors = On
6
+ display_startup_errors = On
7
+ error_reporting = E_ALL
8
+ log_errors = On
@@ -0,0 +1,14 @@
1
+ <VirtualHost *:80>
2
+ ServerName localhost
3
+ DocumentRoot /workspace/apps/cms/web
4
+ <Directory /workspace/apps/cms/web>
5
+ AllowOverride All
6
+ Options +FollowSymLinks -Indexes
7
+ Require all granted
8
+ DirectoryIndex index.php
9
+ </Directory>
10
+ RemoteIPHeader X-Forwarded-For
11
+ SetEnvIfNoCase X-Forwarded-Proto "^https$" HTTPS=on
12
+ ErrorLog /proc/self/fd/2
13
+ CustomLog /proc/self/fd/1 combined
14
+ </VirtualHost>
@@ -0,0 +1,14 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "repository": "registry.smxapp.com/flowpress",
4
+ "runtimes": {
5
+ "cms": {
6
+ "recipe": "0dc3ad5f81ebab17d71d9ad3aeee38f4058a9aab400cfffbd888c34582dc8b50",
7
+ "digest": "sha256:a792ce4c3e9f8942feef09f95f8319febf9e299c1f613c986982905cafdd2f2f"
8
+ },
9
+ "web": {
10
+ "recipe": "58c57037535b075c5d31b03fbbb1ff69c9c19acb9a6c4eb7cc53145980b219a5",
11
+ "digest": "sha256:3455c31d6c56444f0142ea1330b33bc1ae4ab67efc66ce103ca96c59012d4a74"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,8 @@
1
+ FROM node:22.23.2-bookworm-slim@sha256:48e4b67d85f87bd551df43704e24d252f56cc5f8e9718841aace50f19948f0f9
2
+ RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
3
+ && rm -rf /var/lib/apt/lists/* \
4
+ && corepack enable && corepack prepare pnpm@9.15.4 --activate
5
+ COPY local/web/entrypoint.sh /usr/local/bin/flowpress-local-web
6
+ RUN chmod 755 /usr/local/bin/flowpress-local-web
7
+ WORKDIR /workspace
8
+ ENTRYPOINT ["flowpress-local-web"]
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ # Linux dependencies live in Docker volumes, separate from macOS node_modules.
4
+ fingerprint="$(sha256sum pnpm-lock.yaml | cut -d ' ' -f 1)"
5
+ stamp=node_modules/.flowpress-lock
6
+ if [ ! -r "$stamp" ] || [ "$(cat "$stamp")" != "$fingerprint" ]; then
7
+ pnpm install --frozen-lockfile
8
+ printf '%s' "$fingerprint" > "$stamp"
9
+ fi
10
+ pnpm --if-present styleflow:build
11
+ pnpm --if-present components:check
12
+ pnpm --if-present styleflow:watch &
13
+ watcher=$!
14
+ pnpm --filter "$FLOWPRESS_WEB_PACKAGE" dev --ignore-lock &
15
+ frontend=$!
16
+ trap 'kill "$frontend" "$watcher" 2>/dev/null || true; wait || true' EXIT
17
+ trap 'exit 0' INT TERM
18
+ while kill -0 "$frontend" 2>/dev/null; do
19
+ sleep 1
20
+ done
21
+ exit 1
@@ -0,0 +1,21 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ FROM php:8.3-apache-bookworm
3
+ RUN apt-get update && apt-get install -y --no-install-recommends \
4
+ ca-certificates curl default-mysql-client libicu-dev libjpeg62-turbo-dev \
5
+ libpng-dev libwebp-dev libzip-dev unzip webp \
6
+ && docker-php-ext-configure gd --with-jpeg --with-webp \
7
+ && docker-php-ext-install exif gd intl mysqli opcache pdo_mysql zip \
8
+ && a2enmod expires headers remoteip rewrite \
9
+ && rm -rf /var/lib/apt/lists/*
10
+ COPY cms/vhost.conf /etc/apache2/sites-available/000-default.conf
11
+ COPY cms/mpm.conf /etc/apache2/mods-available/mpm_prefork.conf
12
+ COPY cms/php.ini /usr/local/etc/php/conf.d/zz-container.ini
13
+ RUN sed -i 's/^Listen 80$/Listen 8080/' /etc/apache2/ports.conf \
14
+ && sed -i '/Listen 443/d' /etc/apache2/ports.conf \
15
+ && echo 'ServerName localhost' > /etc/apache2/conf-available/servername.conf \
16
+ && a2enconf servername \
17
+ && mkdir -p /tmp/apache2 \
18
+ && chown www-data:www-data /tmp/apache2 \
19
+ && find / -xdev -perm /6000 -type f -exec chmod a-s {} + 2>/dev/null
20
+ ENV APACHE_RUN_DIR=/tmp/apache2 APACHE_PID_FILE=/tmp/apache2/apache2.pid APACHE_LOCK_DIR=/tmp/apache2
21
+ EXPOSE 8080
@@ -0,0 +1,27 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ FROM node:22-bookworm-slim AS dependencies
3
+ RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
4
+ WORKDIR /workspace
5
+ COPY package.json pnpm-lock.yaml pnpm-workspace.yaml .npmrc ./
6
+ COPY apps/web/package.json apps/web/package.json
7
+ COPY apps/cms/package.json apps/cms/package.json
8
+ COPY packages/ui packages/ui
9
+ ARG WEB_PACKAGE
10
+ RUN --mount=type=cache,target=/root/.local/share/pnpm/store pnpm --filter $WEB_PACKAGE --prod deploy /deploy
11
+ FROM node:22-bookworm-slim
12
+ RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl \
13
+ && rm -rf /var/lib/apt/lists/* \
14
+ && find / -xdev -perm /6000 -type f -exec chmod a-s {} + 2>/dev/null
15
+ WORKDIR /srv/web
16
+ COPY --from=dependencies /deploy/node_modules ./node_modules
17
+ ARG DIST_DIR
18
+ COPY $DIST_DIR/ ./dist/
19
+ ARG RELEASE_SHA=unknown
20
+ ARG FRONTEND_BUILD_ID=unknown
21
+ ENV NODE_ENV=production HOST=0.0.0.0 PORT=8080 RELEASE_SHA=$RELEASE_SHA FRONTEND_BUILD_ID=$FRONTEND_BUILD_ID
22
+ LABEL org.opencontainers.image.revision=$RELEASE_SHA
23
+ LABEL app.flowpress.build-id=$FRONTEND_BUILD_ID
24
+ USER node
25
+ EXPOSE 8080
26
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 CMD curl -fsS http://127.0.0.1:8080/healthz.json > /dev/null || exit 1
27
+ CMD ["node", "dist/server/entry.mjs"]
@@ -0,0 +1,10 @@
1
+ .git
2
+ node_modules
3
+ .env*
4
+ .secrets
5
+ .local
6
+ apps/cms/vendor
7
+ apps/cms/auth.json
8
+ apps/cms/.env*
9
+ apps/cms/web
10
+ docs