html-golive 0.4.1__tar.gz

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 (99) hide show
  1. html_golive-0.4.1/LICENSE +21 -0
  2. html_golive-0.4.1/PKG-INFO +324 -0
  3. html_golive-0.4.1/README.md +293 -0
  4. html_golive-0.4.1/golive/__init__.py +3 -0
  5. html_golive-0.4.1/golive/backends/__init__.py +1 -0
  6. html_golive-0.4.1/golive/backends/auth/__init__.py +1 -0
  7. html_golive-0.4.1/golive/backends/auth/base.py +17 -0
  8. html_golive-0.4.1/golive/backends/auth/none.py +12 -0
  9. html_golive-0.4.1/golive/backends/auth/oauth.py +330 -0
  10. html_golive-0.4.1/golive/backends/auth/presets.py +84 -0
  11. html_golive-0.4.1/golive/backends/auth/token.py +49 -0
  12. html_golive-0.4.1/golive/backends/data/__init__.py +5 -0
  13. html_golive-0.4.1/golive/backends/data/supabase.py +151 -0
  14. html_golive-0.4.1/golive/backends/factory.py +51 -0
  15. html_golive-0.4.1/golive/backends/images/__init__.py +15 -0
  16. html_golive-0.4.1/golive/backends/images/base.py +34 -0
  17. html_golive-0.4.1/golive/backends/images/command.py +139 -0
  18. html_golive-0.4.1/golive/backends/images/s3.py +88 -0
  19. html_golive-0.4.1/golive/backends/postgrest.py +138 -0
  20. html_golive-0.4.1/golive/backends/registry/__init__.py +1 -0
  21. html_golive-0.4.1/golive/backends/registry/sqlite_store.py +202 -0
  22. html_golive-0.4.1/golive/backends/registry/supabase_store.py +184 -0
  23. html_golive-0.4.1/golive/backends/storage/__init__.py +1 -0
  24. html_golive-0.4.1/golive/backends/storage/local.py +103 -0
  25. html_golive-0.4.1/golive/backends/storage/s3.py +195 -0
  26. html_golive-0.4.1/golive/backends/storage/supabase_store.py +242 -0
  27. html_golive-0.4.1/golive/cli.py +791 -0
  28. html_golive-0.4.1/golive/config.py +490 -0
  29. html_golive-0.4.1/golive/core/__init__.py +1 -0
  30. html_golive-0.4.1/golive/core/audit_log.py +277 -0
  31. html_golive-0.4.1/golive/core/bundle.py +945 -0
  32. html_golive-0.4.1/golive/core/cdn_localizer.py +222 -0
  33. html_golive-0.4.1/golive/core/clone_analyzer.py +562 -0
  34. html_golive-0.4.1/golive/core/clone_fetcher.py +920 -0
  35. html_golive-0.4.1/golive/core/clone_patcher.py +543 -0
  36. html_golive-0.4.1/golive/core/clone_site.py +315 -0
  37. html_golive-0.4.1/golive/core/code_safety_checker.py +364 -0
  38. html_golive-0.4.1/golive/core/css_style_enhancer.py +659 -0
  39. html_golive-0.4.1/golive/core/data_role_tagger.py +456 -0
  40. html_golive-0.4.1/golive/core/http_client.py +82 -0
  41. html_golive-0.4.1/golive/core/keymap_rules.py +143 -0
  42. html_golive-0.4.1/golive/core/migrate_check.py +189 -0
  43. html_golive-0.4.1/golive/core/paths.py +71 -0
  44. html_golive-0.4.1/golive/core/preview_server.py +780 -0
  45. html_golive-0.4.1/golive/core/publish_utils.py +189 -0
  46. html_golive-0.4.1/golive/core/slug_checker.py +150 -0
  47. html_golive-0.4.1/golive/inject/__init__.py +29 -0
  48. html_golive-0.4.1/golive/inject/_escape.py +72 -0
  49. html_golive-0.4.1/golive/inject/editor.py +434 -0
  50. html_golive-0.4.1/golive/inject/supabase_api.py +309 -0
  51. html_golive-0.4.1/golive/inject/template_api.py +431 -0
  52. html_golive-0.4.1/golive/inject/watermark.py +239 -0
  53. html_golive-0.4.1/golive/resources/css_styles/apple.css +184 -0
  54. html_golive-0.4.1/golive/resources/css_styles/bloomberg.css +208 -0
  55. html_golive-0.4.1/golive/resources/css_styles/carbon.css +145 -0
  56. html_golive-0.4.1/golive/resources/css_styles/cowork.css +184 -0
  57. html_golive-0.4.1/golive/resources/css_styles/cyberpunk.css +269 -0
  58. html_golive-0.4.1/golive/resources/css_styles/dreamy.css +143 -0
  59. html_golive-0.4.1/golive/resources/css_styles/earthy.css +143 -0
  60. html_golive-0.4.1/golive/resources/css_styles/fresh.css +143 -0
  61. html_golive-0.4.1/golive/resources/css_styles/glass.css +157 -0
  62. html_golive-0.4.1/golive/resources/css_styles/ink.css +308 -0
  63. html_golive-0.4.1/golive/resources/css_styles/macaron.css +143 -0
  64. html_golive-0.4.1/golive/resources/css_styles/minimal.css +197 -0
  65. html_golive-0.4.1/golive/resources/css_styles/morandi.css +142 -0
  66. html_golive-0.4.1/golive/resources/css_styles/newspaper.css +317 -0
  67. html_golive-0.4.1/golive/resources/css_styles/palace.css +345 -0
  68. html_golive-0.4.1/golive/resources/css_styles/steampunk.css +215 -0
  69. html_golive-0.4.1/golive/resources/css_styles/vivid.css +152 -0
  70. html_golive-0.4.1/golive/resources/css_styles/xhs-fun.css +209 -0
  71. html_golive-0.4.1/golive/resources/css_styles/xhs.css +183 -0
  72. html_golive-0.4.1/golive/security/__init__.py +1 -0
  73. html_golive-0.4.1/golive/security/ai_review.py +252 -0
  74. html_golive-0.4.1/golive/security/rules.yaml +94 -0
  75. html_golive-0.4.1/golive/security/scanner.py +328 -0
  76. html_golive-0.4.1/golive/server/__init__.py +1 -0
  77. html_golive-0.4.1/golive/server/app.py +395 -0
  78. html_golive-0.4.1/golive/server/editor_api.py +166 -0
  79. html_golive-0.4.1/html_golive.egg-info/PKG-INFO +324 -0
  80. html_golive-0.4.1/html_golive.egg-info/SOURCES.txt +97 -0
  81. html_golive-0.4.1/html_golive.egg-info/dependency_links.txt +1 -0
  82. html_golive-0.4.1/html_golive.egg-info/entry_points.txt +2 -0
  83. html_golive-0.4.1/html_golive.egg-info/requires.txt +9 -0
  84. html_golive-0.4.1/html_golive.egg-info/top_level.txt +1 -0
  85. html_golive-0.4.1/pyproject.toml +48 -0
  86. html_golive-0.4.1/setup.cfg +4 -0
  87. html_golive-0.4.1/tests/test_ai_review.py +211 -0
  88. html_golive-0.4.1/tests/test_backends_supabase.py +137 -0
  89. html_golive-0.4.1/tests/test_config.py +193 -0
  90. html_golive-0.4.1/tests/test_editor.py +310 -0
  91. html_golive-0.4.1/tests/test_inject.py +240 -0
  92. html_golive-0.4.1/tests/test_m2_warn_fixes.py +143 -0
  93. html_golive-0.4.1/tests/test_migrate_check.py +81 -0
  94. html_golive-0.4.1/tests/test_oauth.py +331 -0
  95. html_golive-0.4.1/tests/test_oidc_presets.py +93 -0
  96. html_golive-0.4.1/tests/test_smoke.py +153 -0
  97. html_golive-0.4.1/tests/test_v040_followups.py +80 -0
  98. html_golive-0.4.1/tests/test_v041_hardening.py +99 -0
  99. html_golive-0.4.1/tests/test_watermark.py +145 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Songhonglei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,324 @@
1
+ Metadata-Version: 2.4
2
+ Name: html-golive
3
+ Version: 0.4.1
4
+ Summary: Self-hosted one-command HTML deployment — Vercel-lite for your intranet.
5
+ Author: Songhonglei
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Songhonglei/html-golive
8
+ Project-URL: Issues, https://github.com/Songhonglei/html-golive/issues
9
+ Keywords: html,deploy,static-site,self-hosted,intranet
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: requests>=2.25
24
+ Requires-Dist: beautifulsoup4>=4.9
25
+ Requires-Dist: pyyaml>=5.4
26
+ Provides-Extra: image
27
+ Requires-Dist: Pillow>=9.0; extra == "image"
28
+ Provides-Extra: s3
29
+ Requires-Dist: boto3>=1.26; extra == "s3"
30
+ Dynamic: license-file
31
+
32
+ # html-golive
33
+
34
+ > **Self-hosted one-command HTML deployment — Vercel-lite for your intranet.**
35
+
36
+ Turn any HTML file, project folder or zip archive into a shareable URL on
37
+ your own machine, NAS, VPS or intranet server.
38
+
39
+ ```bash
40
+ pip install git+https://github.com/Songhonglei/html-golive.git
41
+
42
+ golive publish report.html --name "Q3 Report" --slug q3
43
+ # ✅ Published → http://localhost:8787/q3
44
+
45
+ golive serve
46
+ ```
47
+
48
+ **Zero config to start** — local storage + SQLite + built-in server.
49
+ **Grows with you** — swap in Supabase or any S3-compatible backend
50
+ (MinIO / Tencent COS / Aliyun OSS / Volcengine TOS) with one yaml file.
51
+
52
+ ---
53
+
54
+ ## Table of contents
55
+
56
+ - [Why html-golive](#why-html-golive)
57
+ - [Quickstart](#quickstart)
58
+ - [Features](#features)
59
+ - [Architecture](#architecture)
60
+ - [Configuration](#configuration)
61
+ - [Data layer](#data-layer-give-static-pages-a-database)
62
+ - [Security scanning](#security-scanning)
63
+ - [Docker](#docker)
64
+ - [Roadmap](#roadmap)
65
+
66
+ > 📖 **Full user manual**: [docs/manual.md](docs/manual.md) — every feature,
67
+ > organised by task (publishing, editor, access control, data, security,
68
+ > identity, migration, FAQ).
69
+
70
+ ## Why html-golive
71
+
72
+ - **One command, one URL.** No build step, no server code, no cloud
73
+ account. `golive publish` → share the link.
74
+ - **Everything becomes a single file.** Folders and zips are bundled —
75
+ CSS/JS inlined, images compressed and embedded (or uploaded through
76
+ your own image host).
77
+ - **Static pages, real data.** Publish a plain HTML file that reads and
78
+ writes a real database via `window.TemplateAPI` /
79
+ `window.SupabaseAPI` — no backend code required.
80
+ - **Own your stack.** Runs entirely on your infrastructure. No outbound
81
+ calls at publish/serve time ([details](#network-behavior)).
82
+ - **Production habits built in.** Slug collision checks, 10-snapshot
83
+ rollback, credential/PII scanning on every publish, audit log.
84
+
85
+ ## Quickstart
86
+
87
+ ### 1 · Install
88
+
89
+ ```bash
90
+ # from GitHub (PyPI release coming soon)
91
+ pip install git+https://github.com/Songhonglei/html-golive.git
92
+
93
+ # extras once installed from source checkout:
94
+ # pip install '.[image]' # + image compression (Pillow)
95
+ # pip install '.[s3]' # + S3-compatible backends (boto3)
96
+ ```
97
+
98
+ ### 2 · Publish
99
+
100
+ ```bash
101
+ golive publish index.html --name Demo --slug demo
102
+ golive publish ./my-project/ --slug app # folder → bundled single HTML
103
+ golive publish site.zip # zip / tar.gz work too
104
+ golive publish page.html --style apple # apply one of 19 CSS styles
105
+ ```
106
+
107
+ ### 3 · Serve
108
+
109
+ ```bash
110
+ golive serve --port 8787
111
+ # → http://<your-host>:8787/demo
112
+ ```
113
+
114
+ ### Everyday commands
115
+
116
+ ```bash
117
+ golive list # all published sites
118
+ golive publish new.html --update demo # overwrite update
119
+ golive rollback demo --dry-run # inspect snapshots, then --yes
120
+ golive preview draft.html # live preview + style panel
121
+ golive clone https://example.com --save-only # snapshot a public page
122
+ golive styles # list the 19 CSS styles
123
+ golive doctor # environment health check
124
+
125
+ # v0.3 — online editing & watermark
126
+ golive publish page.html --enable-editor --owner you@example.com
127
+ golive maintainer add demo teammate@example.com
128
+ golive publish page.html --watermark "CONFIDENTIAL"
129
+ ```
130
+
131
+ ### Online editing (v0.3)
132
+
133
+ ```bash
134
+ export GOLIVE_EDITOR_TOKEN=$(openssl rand -hex 16)
135
+ golive publish report.html --slug q3 --enable-editor --owner you@example.com
136
+ golive serve
137
+ # open http://localhost:8787/q3?editor_token=<token>&editor_user=you@example.com
138
+ # click ✏️ → edit text inline → 💾 save (snapshot taken automatically)
139
+ ```
140
+
141
+ Saves go through the same security scanner as publishes, are limited to
142
+ the site owner + maintainers, and every overwrite is preceded by a
143
+ rollback snapshot. With `auth.provider: oidc` the editor accepts the
144
+ login session instead of the token+header pair.
145
+
146
+ ## Features
147
+
148
+ **Publishing & content**
149
+ - Single HTML / directory / zip / tar.gz publishing with asset bundling
150
+ - 19 built-in CSS beautification styles (`--style`, custom font CDN via
151
+ `GOLIVE_FONT_CDN_BASE`)
152
+ - Image compression (`--compress`) and pluggable image upload
153
+ (`GOLIVE_UPLOADER_CMD` command template, or native S3 uploader)
154
+ - Website cloning (`golive clone <url>`) with static snapshot mode
155
+
156
+ **Operations**
157
+ - Short slugs with reserved-word and collision checks
158
+ - Rollback with 10 snapshots per site
159
+ - Built-in static server with JSON API and health endpoint
160
+ - Live preview with hot reload and style-switch panel
161
+ - `golive doctor` environment diagnostics, audit log
162
+
163
+ **Data & backends** *(v0.2)*
164
+ - `window.TemplateAPI` / `window.SupabaseAPI` injection — static pages
165
+ get a real database with zero backend code
166
+ - Storage / registry / data backends: local + SQLite (default),
167
+ Supabase (one project covers all three), S3-compatible object storage
168
+ - `golive migrate-check` — port pages from other golive deployments
169
+ - Docker Compose deployment (+ optional MinIO profile)
170
+
171
+ **Editing, identity & watermarking** *(v0.3)*
172
+ - In-browser inline editor (`publish --enable-editor`): contenteditable
173
+ text editing with a save API that re-runs the full security pipeline,
174
+ snapshots before every overwrite, and enforces owner/maintainer ACLs
175
+ (`golive maintainer add/remove/list`)
176
+ - Page watermarking (`--watermark [text]`): canvas-tiled identity
177
+ watermark — OIDC user, static text, or page meta tag; optional
178
+ view-report webhook; `GOLIVE_WATERMARK_OFF=1` kill switch
179
+ - Generic **OIDC login** (`auth.provider: oidc`): Google / Keycloak /
180
+ Authentik / any discovery-document IdP; PKCE + signed session cookies;
181
+ sessions accepted by the management and editor APIs
182
+ - Optional **LLM security review** of weak scan hits via any
183
+ OpenAI-compatible endpoint (`security.llm.*`), with a conservative
184
+ degrade path and a `strict_mode` gate
185
+
186
+ **Safety**
187
+ - Credential / PII scanning on every publish (YAML-extensible rules)
188
+ - Path-traversal-hardened server and archive extraction
189
+ - Token-protected management API (`GOLIVE_TOKEN`)
190
+
191
+ ## Architecture
192
+
193
+ ```
194
+ ┌────────────── golive core (pure logic) ───────────────────┐
195
+ │ bundle / image compress / CSS styles / clone / preview / │
196
+ │ security scanner / slug checker │
197
+ └──────┬──────────────────┬──────────────────┬──────────────┘
198
+ StorageBackend RegistryBackend DataBackend
199
+ site HTML/assets site metadata TemplateAPI/SupabaseAPI
200
+ │ │ │
201
+ local-fs / s3 / SQLite / supabase supabase (PostgREST)
202
+ supabase storage
203
+
204
+ AuthProvider: none (default) / token (GOLIVE_TOKEN) / oidc (generic OIDC)
205
+ ```
206
+
207
+ All data lives under `GOLIVE_HOME` (default `~/.golive/`):
208
+
209
+ ```
210
+ ~/.golive/
211
+ ├── sites/<site_id>/index.html published content
212
+ ├── backups/<site_id>/ rollback snapshots (max 10)
213
+ ├── registry.db SQLite registry
214
+ ├── logs/ audit log
215
+ └── cache/ style backups etc.
216
+ ```
217
+
218
+ ## Configuration
219
+
220
+ Everything works with zero config. Two layers of knobs, **env always
221
+ wins over yaml**:
222
+
223
+ ### golive.yaml (backend selection)
224
+
225
+ Lookup order: `--config <path>` → `$GOLIVE_CONFIG` → `./golive.yaml` →
226
+ `$GOLIVE_HOME/golive.yaml`. Full annotated example:
227
+ [golive.example.yaml](golive.example.yaml) · backend combinations:
228
+ [docs/backends.md](docs/backends.md)
229
+
230
+ ### Environment variables
231
+
232
+ | Variable | Purpose |
233
+ |---|---|
234
+ | `GOLIVE_HOME` | data directory (default `~/.golive/`) |
235
+ | `GOLIVE_TOKEN` | protect `/api/sites` (Bearer or `X-Golive-Token`) |
236
+ | `GOLIVE_EDITOR_TOKEN` | online-editor save token (falls back to `GOLIVE_TOKEN`) |
237
+ | `GOLIVE_WATERMARK_TEXT` / `GOLIVE_WATERMARK_OFF` | watermark text / global kill switch |
238
+ | `GOLIVE_OIDC_CLIENT_SECRET` / `GOLIVE_COOKIE_SECRET` | OIDC client secret / session-cookie HMAC key |
239
+ | `GOLIVE_LLM_BASE_URL` / `GOLIVE_LLM_MODEL` / `GOLIVE_LLM_API_KEY` | LLM security review endpoint |
240
+ | `GOLIVE_FONT_CDN_BASE` | swap `fonts.googleapis.com` for your font mirror |
241
+ | `GOLIVE_UPLOADER_CMD` | image-upload command template (`mytool up {file}`) |
242
+ | `GOLIVE_SUPABASE_URL` / `_ANON_KEY` / `_SERVICE_KEY` | Supabase backends |
243
+ | `GOLIVE_S3_AK` / `GOLIVE_S3_SK` | S3-compatible backends |
244
+ | `FIRECRAWL_API_KEY` | optional JS-heavy-page fallback for `golive clone` |
245
+
246
+ ### Network behavior
247
+
248
+ golive makes **no outbound calls** at publish/serve time. Exceptions:
249
+ `golive clone <url>` fetches the target page; `golive preview` downloads
250
+ a one-time Tailwind cache from `cdn.tailwindcss.com` on first run (fails
251
+ silently offline); injected styles reference public font CDNs
252
+ (override with `GOLIVE_FONT_CDN_BASE`); your own uploader command and
253
+ configured backends.
254
+
255
+ ## Data layer: give static pages a database
256
+
257
+ Backed by your own Supabase project — no server code:
258
+
259
+ ```bash
260
+ golive db init --print-sql # paste into Supabase SQL editor
261
+ golive publish app.html --data-model myapp_v1
262
+ ```
263
+
264
+ Your page then simply calls:
265
+
266
+ ```js
267
+ // namespaced record store
268
+ await TemplateAPI.upsert({ templateName: 'vote:alice', templateContent: {n: 1} });
269
+ const { total, list } = await TemplateAPI.listAll();
270
+
271
+ // or direct table access
272
+ const { rows } = await SupabaseAPI.query('feedback', { limit: 50 });
273
+ ```
274
+
275
+ API signatures are **stable contracts** — pages built on any golive
276
+ deployment run unchanged on yours. Guide with RLS security notes:
277
+ [docs/data-layer.md](docs/data-layer.md).
278
+
279
+ > **Note**: if no data backend is configured, `--data-model` publishes
280
+ > still succeed — the page gets a stub API that raises a clear
281
+ > "data backend not configured" error at call time (a warning is also
282
+ > printed at publish time).
283
+
284
+ Porting pages from another deployment?
285
+ `golive migrate-check page.html` reports anything deployment-specific
286
+ ([migration guide](docs/migrate-from-intranet.md)).
287
+
288
+ ## Security scanning
289
+
290
+ Every publish is scanned against built-in rules — API keys, private
291
+ keys, database connection strings, PII patterns. Strong hits block the
292
+ publish; weak hits warn — and can optionally get a semantic second pass
293
+ from any OpenAI-compatible LLM (`security.llm.base_url`; works with
294
+ OpenAI / Azure / Ollama / self-hosted gateways). Unconfigured installs
295
+ keep pure rule verdicts; `strict_mode: true` refuses to publish without
296
+ AI review. Extend with your own YAML rules, or bypass a false positive
297
+ with `--skip-scan`. Details: [docs/security.md](docs/security.md)
298
+
299
+ ## Docker
300
+
301
+ ```bash
302
+ docker compose up -d golive # golive serve on :8787
303
+ docker compose --profile minio up -d # + local S3 stack for images
304
+ ```
305
+
306
+ ## Roadmap
307
+
308
+ - ~~**M1 — core**: publish/serve/rollback, styles, clone, preview, scan~~ ✅ v0.1
309
+ - ~~**M2 — data layer**: Supabase backend trio, TemplateAPI/SupabaseAPI
310
+ injection, S3 adapters, migrate-check, Docker Compose~~ ✅ v0.2
311
+ - ~~**M3 — editing & identity**: inline editor with versioned save API,
312
+ watermarking, OpenAI-compatible LLM security review, generic OIDC~~ ✅ v0.3
313
+ - ~~**M4 — docs & polish**: OIDC provider presets, editor image upload,
314
+ persistent cookie secret, full user manual~~ ✅ v0.4
315
+ - **M5 — collaboration & scale**: shared session store (redis), multi-user
316
+ editing conflicts UX, group-based ACLs, admin operations portal.
317
+
318
+ ## License
319
+
320
+ [MIT](LICENSE) © 2026 Songhonglei
321
+
322
+ ---
323
+
324
+ 中文文档请见 [README.zh-CN.md](README.zh-CN.md)。
@@ -0,0 +1,293 @@
1
+ # html-golive
2
+
3
+ > **Self-hosted one-command HTML deployment — Vercel-lite for your intranet.**
4
+
5
+ Turn any HTML file, project folder or zip archive into a shareable URL on
6
+ your own machine, NAS, VPS or intranet server.
7
+
8
+ ```bash
9
+ pip install git+https://github.com/Songhonglei/html-golive.git
10
+
11
+ golive publish report.html --name "Q3 Report" --slug q3
12
+ # ✅ Published → http://localhost:8787/q3
13
+
14
+ golive serve
15
+ ```
16
+
17
+ **Zero config to start** — local storage + SQLite + built-in server.
18
+ **Grows with you** — swap in Supabase or any S3-compatible backend
19
+ (MinIO / Tencent COS / Aliyun OSS / Volcengine TOS) with one yaml file.
20
+
21
+ ---
22
+
23
+ ## Table of contents
24
+
25
+ - [Why html-golive](#why-html-golive)
26
+ - [Quickstart](#quickstart)
27
+ - [Features](#features)
28
+ - [Architecture](#architecture)
29
+ - [Configuration](#configuration)
30
+ - [Data layer](#data-layer-give-static-pages-a-database)
31
+ - [Security scanning](#security-scanning)
32
+ - [Docker](#docker)
33
+ - [Roadmap](#roadmap)
34
+
35
+ > 📖 **Full user manual**: [docs/manual.md](docs/manual.md) — every feature,
36
+ > organised by task (publishing, editor, access control, data, security,
37
+ > identity, migration, FAQ).
38
+
39
+ ## Why html-golive
40
+
41
+ - **One command, one URL.** No build step, no server code, no cloud
42
+ account. `golive publish` → share the link.
43
+ - **Everything becomes a single file.** Folders and zips are bundled —
44
+ CSS/JS inlined, images compressed and embedded (or uploaded through
45
+ your own image host).
46
+ - **Static pages, real data.** Publish a plain HTML file that reads and
47
+ writes a real database via `window.TemplateAPI` /
48
+ `window.SupabaseAPI` — no backend code required.
49
+ - **Own your stack.** Runs entirely on your infrastructure. No outbound
50
+ calls at publish/serve time ([details](#network-behavior)).
51
+ - **Production habits built in.** Slug collision checks, 10-snapshot
52
+ rollback, credential/PII scanning on every publish, audit log.
53
+
54
+ ## Quickstart
55
+
56
+ ### 1 · Install
57
+
58
+ ```bash
59
+ # from GitHub (PyPI release coming soon)
60
+ pip install git+https://github.com/Songhonglei/html-golive.git
61
+
62
+ # extras once installed from source checkout:
63
+ # pip install '.[image]' # + image compression (Pillow)
64
+ # pip install '.[s3]' # + S3-compatible backends (boto3)
65
+ ```
66
+
67
+ ### 2 · Publish
68
+
69
+ ```bash
70
+ golive publish index.html --name Demo --slug demo
71
+ golive publish ./my-project/ --slug app # folder → bundled single HTML
72
+ golive publish site.zip # zip / tar.gz work too
73
+ golive publish page.html --style apple # apply one of 19 CSS styles
74
+ ```
75
+
76
+ ### 3 · Serve
77
+
78
+ ```bash
79
+ golive serve --port 8787
80
+ # → http://<your-host>:8787/demo
81
+ ```
82
+
83
+ ### Everyday commands
84
+
85
+ ```bash
86
+ golive list # all published sites
87
+ golive publish new.html --update demo # overwrite update
88
+ golive rollback demo --dry-run # inspect snapshots, then --yes
89
+ golive preview draft.html # live preview + style panel
90
+ golive clone https://example.com --save-only # snapshot a public page
91
+ golive styles # list the 19 CSS styles
92
+ golive doctor # environment health check
93
+
94
+ # v0.3 — online editing & watermark
95
+ golive publish page.html --enable-editor --owner you@example.com
96
+ golive maintainer add demo teammate@example.com
97
+ golive publish page.html --watermark "CONFIDENTIAL"
98
+ ```
99
+
100
+ ### Online editing (v0.3)
101
+
102
+ ```bash
103
+ export GOLIVE_EDITOR_TOKEN=$(openssl rand -hex 16)
104
+ golive publish report.html --slug q3 --enable-editor --owner you@example.com
105
+ golive serve
106
+ # open http://localhost:8787/q3?editor_token=<token>&editor_user=you@example.com
107
+ # click ✏️ → edit text inline → 💾 save (snapshot taken automatically)
108
+ ```
109
+
110
+ Saves go through the same security scanner as publishes, are limited to
111
+ the site owner + maintainers, and every overwrite is preceded by a
112
+ rollback snapshot. With `auth.provider: oidc` the editor accepts the
113
+ login session instead of the token+header pair.
114
+
115
+ ## Features
116
+
117
+ **Publishing & content**
118
+ - Single HTML / directory / zip / tar.gz publishing with asset bundling
119
+ - 19 built-in CSS beautification styles (`--style`, custom font CDN via
120
+ `GOLIVE_FONT_CDN_BASE`)
121
+ - Image compression (`--compress`) and pluggable image upload
122
+ (`GOLIVE_UPLOADER_CMD` command template, or native S3 uploader)
123
+ - Website cloning (`golive clone <url>`) with static snapshot mode
124
+
125
+ **Operations**
126
+ - Short slugs with reserved-word and collision checks
127
+ - Rollback with 10 snapshots per site
128
+ - Built-in static server with JSON API and health endpoint
129
+ - Live preview with hot reload and style-switch panel
130
+ - `golive doctor` environment diagnostics, audit log
131
+
132
+ **Data & backends** *(v0.2)*
133
+ - `window.TemplateAPI` / `window.SupabaseAPI` injection — static pages
134
+ get a real database with zero backend code
135
+ - Storage / registry / data backends: local + SQLite (default),
136
+ Supabase (one project covers all three), S3-compatible object storage
137
+ - `golive migrate-check` — port pages from other golive deployments
138
+ - Docker Compose deployment (+ optional MinIO profile)
139
+
140
+ **Editing, identity & watermarking** *(v0.3)*
141
+ - In-browser inline editor (`publish --enable-editor`): contenteditable
142
+ text editing with a save API that re-runs the full security pipeline,
143
+ snapshots before every overwrite, and enforces owner/maintainer ACLs
144
+ (`golive maintainer add/remove/list`)
145
+ - Page watermarking (`--watermark [text]`): canvas-tiled identity
146
+ watermark — OIDC user, static text, or page meta tag; optional
147
+ view-report webhook; `GOLIVE_WATERMARK_OFF=1` kill switch
148
+ - Generic **OIDC login** (`auth.provider: oidc`): Google / Keycloak /
149
+ Authentik / any discovery-document IdP; PKCE + signed session cookies;
150
+ sessions accepted by the management and editor APIs
151
+ - Optional **LLM security review** of weak scan hits via any
152
+ OpenAI-compatible endpoint (`security.llm.*`), with a conservative
153
+ degrade path and a `strict_mode` gate
154
+
155
+ **Safety**
156
+ - Credential / PII scanning on every publish (YAML-extensible rules)
157
+ - Path-traversal-hardened server and archive extraction
158
+ - Token-protected management API (`GOLIVE_TOKEN`)
159
+
160
+ ## Architecture
161
+
162
+ ```
163
+ ┌────────────── golive core (pure logic) ───────────────────┐
164
+ │ bundle / image compress / CSS styles / clone / preview / │
165
+ │ security scanner / slug checker │
166
+ └──────┬──────────────────┬──────────────────┬──────────────┘
167
+ StorageBackend RegistryBackend DataBackend
168
+ site HTML/assets site metadata TemplateAPI/SupabaseAPI
169
+ │ │ │
170
+ local-fs / s3 / SQLite / supabase supabase (PostgREST)
171
+ supabase storage
172
+
173
+ AuthProvider: none (default) / token (GOLIVE_TOKEN) / oidc (generic OIDC)
174
+ ```
175
+
176
+ All data lives under `GOLIVE_HOME` (default `~/.golive/`):
177
+
178
+ ```
179
+ ~/.golive/
180
+ ├── sites/<site_id>/index.html published content
181
+ ├── backups/<site_id>/ rollback snapshots (max 10)
182
+ ├── registry.db SQLite registry
183
+ ├── logs/ audit log
184
+ └── cache/ style backups etc.
185
+ ```
186
+
187
+ ## Configuration
188
+
189
+ Everything works with zero config. Two layers of knobs, **env always
190
+ wins over yaml**:
191
+
192
+ ### golive.yaml (backend selection)
193
+
194
+ Lookup order: `--config <path>` → `$GOLIVE_CONFIG` → `./golive.yaml` →
195
+ `$GOLIVE_HOME/golive.yaml`. Full annotated example:
196
+ [golive.example.yaml](golive.example.yaml) · backend combinations:
197
+ [docs/backends.md](docs/backends.md)
198
+
199
+ ### Environment variables
200
+
201
+ | Variable | Purpose |
202
+ |---|---|
203
+ | `GOLIVE_HOME` | data directory (default `~/.golive/`) |
204
+ | `GOLIVE_TOKEN` | protect `/api/sites` (Bearer or `X-Golive-Token`) |
205
+ | `GOLIVE_EDITOR_TOKEN` | online-editor save token (falls back to `GOLIVE_TOKEN`) |
206
+ | `GOLIVE_WATERMARK_TEXT` / `GOLIVE_WATERMARK_OFF` | watermark text / global kill switch |
207
+ | `GOLIVE_OIDC_CLIENT_SECRET` / `GOLIVE_COOKIE_SECRET` | OIDC client secret / session-cookie HMAC key |
208
+ | `GOLIVE_LLM_BASE_URL` / `GOLIVE_LLM_MODEL` / `GOLIVE_LLM_API_KEY` | LLM security review endpoint |
209
+ | `GOLIVE_FONT_CDN_BASE` | swap `fonts.googleapis.com` for your font mirror |
210
+ | `GOLIVE_UPLOADER_CMD` | image-upload command template (`mytool up {file}`) |
211
+ | `GOLIVE_SUPABASE_URL` / `_ANON_KEY` / `_SERVICE_KEY` | Supabase backends |
212
+ | `GOLIVE_S3_AK` / `GOLIVE_S3_SK` | S3-compatible backends |
213
+ | `FIRECRAWL_API_KEY` | optional JS-heavy-page fallback for `golive clone` |
214
+
215
+ ### Network behavior
216
+
217
+ golive makes **no outbound calls** at publish/serve time. Exceptions:
218
+ `golive clone <url>` fetches the target page; `golive preview` downloads
219
+ a one-time Tailwind cache from `cdn.tailwindcss.com` on first run (fails
220
+ silently offline); injected styles reference public font CDNs
221
+ (override with `GOLIVE_FONT_CDN_BASE`); your own uploader command and
222
+ configured backends.
223
+
224
+ ## Data layer: give static pages a database
225
+
226
+ Backed by your own Supabase project — no server code:
227
+
228
+ ```bash
229
+ golive db init --print-sql # paste into Supabase SQL editor
230
+ golive publish app.html --data-model myapp_v1
231
+ ```
232
+
233
+ Your page then simply calls:
234
+
235
+ ```js
236
+ // namespaced record store
237
+ await TemplateAPI.upsert({ templateName: 'vote:alice', templateContent: {n: 1} });
238
+ const { total, list } = await TemplateAPI.listAll();
239
+
240
+ // or direct table access
241
+ const { rows } = await SupabaseAPI.query('feedback', { limit: 50 });
242
+ ```
243
+
244
+ API signatures are **stable contracts** — pages built on any golive
245
+ deployment run unchanged on yours. Guide with RLS security notes:
246
+ [docs/data-layer.md](docs/data-layer.md).
247
+
248
+ > **Note**: if no data backend is configured, `--data-model` publishes
249
+ > still succeed — the page gets a stub API that raises a clear
250
+ > "data backend not configured" error at call time (a warning is also
251
+ > printed at publish time).
252
+
253
+ Porting pages from another deployment?
254
+ `golive migrate-check page.html` reports anything deployment-specific
255
+ ([migration guide](docs/migrate-from-intranet.md)).
256
+
257
+ ## Security scanning
258
+
259
+ Every publish is scanned against built-in rules — API keys, private
260
+ keys, database connection strings, PII patterns. Strong hits block the
261
+ publish; weak hits warn — and can optionally get a semantic second pass
262
+ from any OpenAI-compatible LLM (`security.llm.base_url`; works with
263
+ OpenAI / Azure / Ollama / self-hosted gateways). Unconfigured installs
264
+ keep pure rule verdicts; `strict_mode: true` refuses to publish without
265
+ AI review. Extend with your own YAML rules, or bypass a false positive
266
+ with `--skip-scan`. Details: [docs/security.md](docs/security.md)
267
+
268
+ ## Docker
269
+
270
+ ```bash
271
+ docker compose up -d golive # golive serve on :8787
272
+ docker compose --profile minio up -d # + local S3 stack for images
273
+ ```
274
+
275
+ ## Roadmap
276
+
277
+ - ~~**M1 — core**: publish/serve/rollback, styles, clone, preview, scan~~ ✅ v0.1
278
+ - ~~**M2 — data layer**: Supabase backend trio, TemplateAPI/SupabaseAPI
279
+ injection, S3 adapters, migrate-check, Docker Compose~~ ✅ v0.2
280
+ - ~~**M3 — editing & identity**: inline editor with versioned save API,
281
+ watermarking, OpenAI-compatible LLM security review, generic OIDC~~ ✅ v0.3
282
+ - ~~**M4 — docs & polish**: OIDC provider presets, editor image upload,
283
+ persistent cookie secret, full user manual~~ ✅ v0.4
284
+ - **M5 — collaboration & scale**: shared session store (redis), multi-user
285
+ editing conflicts UX, group-based ACLs, admin operations portal.
286
+
287
+ ## License
288
+
289
+ [MIT](LICENSE) © 2026 Songhonglei
290
+
291
+ ---
292
+
293
+ 中文文档请见 [README.zh-CN.md](README.zh-CN.md)。
@@ -0,0 +1,3 @@
1
+ """html-golive — self-hosted one-command HTML deployment."""
2
+
3
+ __version__ = "0.4.1"
@@ -0,0 +1,17 @@
1
+ """golive.backends.auth.base — AuthProvider interface."""
2
+
3
+ from abc import ABC, abstractmethod
4
+
5
+
6
+ class AuthProvider(ABC):
7
+ """Auth abstraction for serve-mode write operations (and M3 editor)."""
8
+
9
+ name = "base"
10
+
11
+ @abstractmethod
12
+ def verify(self, request_headers: dict) -> bool:
13
+ """Return True when the request is allowed to perform write ops."""
14
+
15
+ def identity(self, request_headers: dict) -> str:
16
+ """Best-effort caller identity (empty string when unknown)."""
17
+ return ""
@@ -0,0 +1,12 @@
1
+ """golive.backends.auth.none — no-auth provider (default for single-user)."""
2
+
3
+ from golive.backends.auth.base import AuthProvider
4
+
5
+
6
+ class NoneAuth(AuthProvider):
7
+ """Allows everything. Fine on localhost; use TokenAuth on shared hosts."""
8
+
9
+ name = "none"
10
+
11
+ def verify(self, request_headers: dict) -> bool:
12
+ return True