@swissjs/swite 0.3.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.
- package/.changeset/config.json +11 -0
- package/.github/workflows/ci.yml +59 -0
- package/.github/workflows/publish.yml +50 -0
- package/.github/workflows/release.yml +53 -0
- package/BUILD_ANALYSIS.md +89 -0
- package/BUILD_STRATEGY.md +75 -0
- package/CHANGELOG.md +53 -0
- package/DIRECTIVE.md +488 -0
- package/__tests__/css-extraction.test.ts +261 -0
- package/__tests__/css-injection-integration.test.ts +247 -0
- package/__tests__/css-middleware.test.ts +191 -0
- package/__tests__/import-rewriter-bug.test.ts +135 -0
- package/dist/builder.d.ts +36 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +772 -0
- package/dist/cache/compilation-cache.d.ts +33 -0
- package/dist/cache/compilation-cache.d.ts.map +1 -0
- package/dist/cache/compilation-cache.js +130 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +85 -0
- package/dist/config-loader.d.ts +8 -0
- package/dist/config-loader.d.ts.map +1 -0
- package/dist/config-loader.js +40 -0
- package/dist/config.d.ts +29 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +7 -0
- package/dist/dev/pythonDevManager.d.ts +12 -0
- package/dist/dev/pythonDevManager.d.ts.map +1 -0
- package/dist/dev/pythonDevManager.js +85 -0
- package/dist/env.d.ts +19 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +112 -0
- package/dist/handlers/base-handler.d.ts +21 -0
- package/dist/handlers/base-handler.d.ts.map +1 -0
- package/dist/handlers/base-handler.js +38 -0
- package/dist/handlers/js-handler.d.ts +10 -0
- package/dist/handlers/js-handler.d.ts.map +1 -0
- package/dist/handlers/js-handler.js +87 -0
- package/dist/handlers/mjs-handler.d.ts +8 -0
- package/dist/handlers/mjs-handler.d.ts.map +1 -0
- package/dist/handlers/mjs-handler.js +44 -0
- package/dist/handlers/node-module-handler.d.ts +16 -0
- package/dist/handlers/node-module-handler.d.ts.map +1 -0
- package/dist/handlers/node-module-handler.js +267 -0
- package/dist/handlers/ts-handler.d.ts +11 -0
- package/dist/handlers/ts-handler.d.ts.map +1 -0
- package/dist/handlers/ts-handler.js +120 -0
- package/dist/handlers/ui-handler.d.ts +12 -0
- package/dist/handlers/ui-handler.d.ts.map +1 -0
- package/dist/handlers/ui-handler.js +182 -0
- package/dist/handlers/uix-handler.d.ts +12 -0
- package/dist/handlers/uix-handler.d.ts.map +1 -0
- package/dist/handlers/uix-handler.js +135 -0
- package/dist/hmr.d.ts +20 -0
- package/dist/hmr.d.ts.map +1 -0
- package/dist/hmr.js +265 -0
- package/dist/import-rewriter.d.ts +3 -0
- package/dist/import-rewriter.d.ts.map +1 -0
- package/dist/import-rewriter.js +351 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/middleware/hmr-routes.d.ts +12 -0
- package/dist/middleware/hmr-routes.d.ts.map +1 -0
- package/dist/middleware/hmr-routes.js +97 -0
- package/dist/middleware/middleware-setup.d.ts +23 -0
- package/dist/middleware/middleware-setup.d.ts.map +1 -0
- package/dist/middleware/middleware-setup.js +596 -0
- package/dist/middleware/static-files.d.ts +15 -0
- package/dist/middleware/static-files.d.ts.map +1 -0
- package/dist/middleware/static-files.js +585 -0
- package/dist/proxy/SwiteProxyError.d.ts +6 -0
- package/dist/proxy/SwiteProxyError.d.ts.map +1 -0
- package/dist/proxy/SwiteProxyError.js +9 -0
- package/dist/proxy/proxyToPython.d.ts +28 -0
- package/dist/proxy/proxyToPython.d.ts.map +1 -0
- package/dist/proxy/proxyToPython.js +66 -0
- package/dist/resolver/bare-import-resolver.d.ts +9 -0
- package/dist/resolver/bare-import-resolver.d.ts.map +1 -0
- package/dist/resolver/bare-import-resolver.js +363 -0
- package/dist/resolver/symlink-registry.d.ts +13 -0
- package/dist/resolver/symlink-registry.d.ts.map +1 -0
- package/dist/resolver/symlink-registry.js +98 -0
- package/dist/resolver/url-resolver.d.ts +11 -0
- package/dist/resolver/url-resolver.d.ts.map +1 -0
- package/dist/resolver/url-resolver.js +268 -0
- package/dist/resolver/workspace-package-resolver.d.ts +10 -0
- package/dist/resolver/workspace-package-resolver.d.ts.map +1 -0
- package/dist/resolver/workspace-package-resolver.js +185 -0
- package/dist/resolver.d.ts +17 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +191 -0
- package/dist/router/file-router.d.ts +19 -0
- package/dist/router/file-router.d.ts.map +1 -0
- package/dist/router/file-router.js +114 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +122 -0
- package/dist/utils/cdn-fallback.d.ts +14 -0
- package/dist/utils/cdn-fallback.d.ts.map +1 -0
- package/dist/utils/cdn-fallback.js +36 -0
- package/dist/utils/file-path-resolver.d.ts +9 -0
- package/dist/utils/file-path-resolver.d.ts.map +1 -0
- package/dist/utils/file-path-resolver.js +187 -0
- package/dist/utils/generate-import-map-cli.d.ts +3 -0
- package/dist/utils/generate-import-map-cli.d.ts.map +1 -0
- package/dist/utils/generate-import-map-cli.js +32 -0
- package/dist/utils/generate-import-map.d.ts +21 -0
- package/dist/utils/generate-import-map.d.ts.map +1 -0
- package/dist/utils/generate-import-map.js +119 -0
- package/dist/utils/package-finder.d.ts +24 -0
- package/dist/utils/package-finder.d.ts.map +1 -0
- package/dist/utils/package-finder.js +161 -0
- package/dist/utils/package-registry.d.ts +36 -0
- package/dist/utils/package-registry.d.ts.map +1 -0
- package/dist/utils/package-registry.js +159 -0
- package/dist/utils/workspace.d.ts +6 -0
- package/dist/utils/workspace.d.ts.map +1 -0
- package/dist/utils/workspace.js +65 -0
- package/docs/IMPORT_REWRITING.md +164 -0
- package/docs/IMPORT_REWRITING_TROUBLESHOOTING.md +139 -0
- package/docs/PATH_RESOLUTION_GUIDE.md +221 -0
- package/package.json +49 -0
- package/src/adapters/proxy/SwiteProxyError.ts +12 -0
- package/src/adapters/proxy/proxyToPython.ts +88 -0
- package/src/build-engine/builder.ts +960 -0
- package/src/cli.ts +109 -0
- package/src/config/config-loader.ts +46 -0
- package/src/config/config.ts +34 -0
- package/src/config/env.ts +98 -0
- package/src/dev-engine/handlers/base-handler.ts +68 -0
- package/src/dev-engine/handlers/js-handler.ts +134 -0
- package/src/dev-engine/handlers/mjs-handler.ts +65 -0
- package/src/dev-engine/handlers/node-module-handler.ts +339 -0
- package/src/dev-engine/handlers/ts-handler.ts +143 -0
- package/src/dev-engine/handlers/ui-handler.ts +105 -0
- package/src/dev-engine/handlers/uix-handler.ts +90 -0
- package/src/dev-engine/hmr/hmr-client-template.ts +122 -0
- package/src/dev-engine/hmr/hmr.ts +173 -0
- package/src/dev-engine/middleware/hmr-routes.ts +120 -0
- package/src/dev-engine/middleware/middleware-setup.ts +351 -0
- package/src/dev-engine/middleware/static-files.ts +728 -0
- package/src/dev-engine/pythonDevManager.ts +116 -0
- package/src/dev-engine/router/file-router.ts +164 -0
- package/src/dev-engine/server.ts +152 -0
- package/src/index.ts +26 -0
- package/src/internal/cache/compilation-cache.ts +182 -0
- package/src/internal/generate-import-map-cli.ts +40 -0
- package/src/internal/generate-import-map.ts +154 -0
- package/src/kernel/package-finder.ts +164 -0
- package/src/kernel/package-registry.ts +198 -0
- package/src/kernel/workspace.ts +62 -0
- package/src/resolution/bare-import-resolver.ts +400 -0
- package/src/resolution/cdn/cdn-fallback.ts +37 -0
- package/src/resolution/path/file-path-resolver.ts +190 -0
- package/src/resolution/path/path-fixup.ts +19 -0
- package/src/resolution/resolver.ts +198 -0
- package/src/resolution/rewriting/import-rewriter.ts +237 -0
- package/src/resolution/symlink-registry.ts +114 -0
- package/src/resolution/url-resolver.ts +231 -0
- package/src/resolution/workspace-package-resolver.ts +94 -0
- package/tsconfig.json +37 -0
package/DIRECTIVE.md
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# DIRECTIVE — swite
|
|
2
|
+
> Last updated: 2026-05-19 · Owner: Kibologic · Repo: kibologic/swite
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Status
|
|
7
|
+
`IN ACTIVE DEVELOPMENT` — Core dev server functional. Python service integration not yet implemented. This is the primary sprint focus.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Current Sprint
|
|
12
|
+
|
|
13
|
+
### S-01 — swiss.config.ts Python Service Schema
|
|
14
|
+
Define the `services.python` config block type. This is the foundation everything else in this sprint depends on.
|
|
15
|
+
|
|
16
|
+
Target API:
|
|
17
|
+
```ts
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
server: { port: 3000 },
|
|
20
|
+
services: {
|
|
21
|
+
python: {
|
|
22
|
+
entry: './services/main.py',
|
|
23
|
+
port: 8000,
|
|
24
|
+
autoStart: true,
|
|
25
|
+
healthCheck: '/health',
|
|
26
|
+
env: {},
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Acceptance: `defineConfig` accepts and types the `services.python` block without errors. Unknown fields are rejected by TypeScript.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### S-02 — proxyToPython Utility
|
|
37
|
+
Internal proxy function that Node route handlers use to communicate with the Python service. Lives in `packages/swite/src/proxy.ts`.
|
|
38
|
+
|
|
39
|
+
Requirements:
|
|
40
|
+
- Accepts path + RequestInit options
|
|
41
|
+
- Reads `PYTHON_SERVICE_URL` from env (default: http://localhost:8000)
|
|
42
|
+
- Attaches `X-Internal-Token` header from env
|
|
43
|
+
- Throws typed `SwiteProxyError` on non-2xx responses
|
|
44
|
+
- Fully typed — no `any`, generic return type
|
|
45
|
+
|
|
46
|
+
Acceptance: A route handler can call `proxyToPython<MyType>('/some/path')` and get back a typed response.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### S-03 — CLI Dev Process Manager
|
|
51
|
+
Extend `swite dev` command to spawn and manage the Python process when `services.python.autoStart` is true.
|
|
52
|
+
|
|
53
|
+
Sequence:
|
|
54
|
+
1. Read `swiss.config.ts` — check if `services.python` is defined
|
|
55
|
+
2. Spawn Python via `uvicorn services.main:app --port {port} --reload`
|
|
56
|
+
3. Poll `healthCheck` endpoint every 500ms — max 30s timeout
|
|
57
|
+
4. Once healthy — start Node server
|
|
58
|
+
5. Stream both process logs prefixed `[node]` and `[python]`
|
|
59
|
+
6. On Python crash — log prominently, continue Node in degraded mode
|
|
60
|
+
7. On Ctrl+C — kill both processes cleanly
|
|
61
|
+
|
|
62
|
+
Acceptance: Running `swite dev` in Alpine ERP boots both servers. Killing one does not orphan the other.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
### S-04 — Production Mode
|
|
67
|
+
`swite start` must not attempt to spawn Python. Reads `PYTHON_SERVICE_URL` from env only.
|
|
68
|
+
|
|
69
|
+
Acceptance: `swite start` with no `PYTHON_SERVICE_URL` set logs a clear warning but does not crash.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
### ✅ S-06 — Fix module resolver — search parent node_modules (COMPLETED 2026-03-26)
|
|
74
|
+
Added `path.join(path.dirname(context.root), "node_modules")` to `nodeModulesLocations`
|
|
75
|
+
in `src/resolver/bare-import-resolver.ts`. Resolver now checks parent directory node_modules
|
|
76
|
+
in addition to app root and workspace root.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### ✅ S-08 — Support monorepo rootDir in dev server (COMPLETED 2026-02-28)
|
|
81
|
+
|
|
82
|
+
Swite's serve root must be configurable to cover the full monorepo.
|
|
83
|
+
Apps import from sibling `packages/` and `modules/` directories outside
|
|
84
|
+
the app folder. Add `rootDir` to `swiss.config.ts` schema — distinct from
|
|
85
|
+
`root` (app source directory). The dev server must be able to resolve and
|
|
86
|
+
serve files anywhere within `rootDir`.
|
|
87
|
+
|
|
88
|
+
**Files modified:**
|
|
89
|
+
|
|
90
|
+
- `src/server.ts` — added `rootDir` to `SwiteConfig`, exported `defineConfig`, resolves rootDir to absolute
|
|
91
|
+
- `src/resolver.ts` — `ModuleResolver` accepts optional `rootDir`, passes to `UrlResolverContext`
|
|
92
|
+
- `src/resolver/url-resolver.ts` — `toUrl` checks rootDir before workspace root to generate clean URLs
|
|
93
|
+
- `src/utils/file-path-resolver.ts` — `resolveFilePath` uses rootDir as fallback when workspace root is null
|
|
94
|
+
- `src/handlers/base-handler.ts` — `HandlerContext` includes rootDir, passes to resolveFilePath
|
|
95
|
+
- `src/middleware/middleware-setup.ts` — `MiddlewareConfig` includes rootDir, passes to handlerContext
|
|
96
|
+
- `src/index.ts` — exports `defineConfig`
|
|
97
|
+
- `src/resolver/bare-import-resolver.ts` — removed dead code (lines 128–262) that blocked build
|
|
98
|
+
|
|
99
|
+
**Verified in alpine-erp (2026-02-28):**
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
GET /packages/core/src/index.ui → 200 ✅
|
|
103
|
+
GET /modules/dashboard/src/index.ui → 200 ✅
|
|
104
|
+
GET /modules/users/src/index.ui → 200 ✅
|
|
105
|
+
GET /modules/settings/src/index.ui → 200 ✅
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### ✅ S-09 — Fix MIME type for .ui/.uix and .ts responses (COMPLETED 2026-02-28)
|
|
111
|
+
|
|
112
|
+
Swite was returning `text/html` for `.uix` and `.ts` non-cached responses.
|
|
113
|
+
`res.send()` in Express defaults to `text/html` when no Content-Type is set.
|
|
114
|
+
|
|
115
|
+
**Root cause:** `uix-handler.ts` and `ts-handler.ts` set Content-Type on the
|
|
116
|
+
cached path but not on the non-cached (compile) path.
|
|
117
|
+
|
|
118
|
+
**Fix:** Added `res.setHeader("Content-Type", "application/javascript; charset=utf-8")`
|
|
119
|
+
before `res.send()` in:
|
|
120
|
+
|
|
121
|
+
- `src/handlers/uix-handler.ts` (line 175)
|
|
122
|
+
- `src/handlers/ts-handler.ts` (line 166)
|
|
123
|
+
|
|
124
|
+
**Verified:** `App.uix`, `index.ts`, `index.ui` all return `Content-Type: application/javascript`.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### ✅ S-07 — Fix findSwissLibMonorepo path (COMPLETED 2026-03-26)
|
|
129
|
+
`findSwissLibMonorepo` in `src/utils/package-finder.ts` now scans immediate
|
|
130
|
+
subdirectories of each ancestor (excluding node_modules) for a `swiss-lib/` child.
|
|
131
|
+
Handles `SWS/swiss-lib/` and any other one-level-deep monorepo layouts.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Blocked
|
|
136
|
+
_Nothing blocked currently._
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Swiss Gaps
|
|
141
|
+
> Gaps discovered in swiss-lib during swite development. Each becomes a swiss-lib task.
|
|
142
|
+
|
|
143
|
+
_None discovered yet. Populate as development proceeds._
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Compiler Gaps
|
|
148
|
+
> Discovered during alpine-mobile Phase 5 build (2026-03-26). All fixed as hotfixes in swite/dist/ — need porting to swite source before next version cut.
|
|
149
|
+
|
|
150
|
+
- **CG-01** CLI entry hardcoded as `.ts` — should resolve `.ui` — FIXED in source `src/cli.ts` line 76
|
|
151
|
+
- **CG-02** `@swissjs/*` and `@skltn/*` not in externals — bundled instead of left as browser imports — FIXED in source `src/builder.ts` nodeBuiltins
|
|
152
|
+
- **CG-03** `findSwissFiles`/`findFiles` do not follow NTFS junctions (`isSymbolicLink()` check missing) — FIXED in source `src/builder.ts`
|
|
153
|
+
- **CG-04** Traversal enters `node_modules` via symlinks — `node_modules` not excluded from junction traversal — FIXED in source `src/builder.ts`
|
|
154
|
+
- **CG-05** `UiCompiler` rewrites `.ui` imports to `.js` but emits `.tsx` files — `jsTsxFallbackPlugin` added — FIXED in source `src/builder.ts`
|
|
155
|
+
- **CG-06** Compiler emits named exports only — default imports fail at bundle time — `export default` injected post-compile — FIXED in source `src/builder.ts`
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Session Log
|
|
160
|
+
|
|
161
|
+
### 2026-03-26
|
|
162
|
+
|
|
163
|
+
- Logged CG-01 through CG-06 from alpine-mobile Phase 5 build
|
|
164
|
+
- All 6 fixed in swite/dist/ as hotfixes — need porting to swite source before next version cut
|
|
165
|
+
- Fixed CG-01 through CG-06 in swite source (src/cli.ts + src/builder.ts)
|
|
166
|
+
- swite tsc build fails on swiss-lib project reference errors (pre-existing TD-02) — dist updated via linter auto-compile
|
|
167
|
+
- Verified alpine-mobile build passes end-to-end: dist/index.js 30.5kb ✅
|
|
168
|
+
- Fixed S-06: parent node_modules added to bare-import-resolver nodeModulesLocations
|
|
169
|
+
- Fixed S-07: findSwissLibMonorepo now scans immediate subdirs one level deeper
|
|
170
|
+
- alpine-mobile build on Linux blocked by missing NTFS junctions (src/modules, src/packages) — pre-existing Linux env constraint, not caused by these changes
|
|
171
|
+
- Commit: 4cf8c6e
|
|
172
|
+
- Bumped version to 0.2.0 (commit fd039ce) — wrote CHANGELOG.md covering CG-01–06 and 0.1.0 baseline
|
|
173
|
+
- swiss-lib CG fixes committed (commit 6d9c296): CG-03/04/05 in compiler + core hookRegistry alignment + cli traversal
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Done
|
|
178
|
+
_Nothing completed yet. Append items here as sprints close._
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Versioning & Release Strategy (locked 2026-03-01)
|
|
183
|
+
|
|
184
|
+
### Decisions
|
|
185
|
+
- Registry: npm public registry (MIT license)
|
|
186
|
+
- Scope: @swissjs/swite
|
|
187
|
+
- Cadence: milestone-based, versions with swiss-lib
|
|
188
|
+
- Changesets: @changesets/cli
|
|
189
|
+
- Pre-v1: publish 0.1.0 NOW alongside swiss-lib
|
|
190
|
+
|
|
191
|
+
### Pipeline (LIVE — commit cefd6ef, 2026-03-02)
|
|
192
|
+
|
|
193
|
+
File: .github/workflows/ci.yml ✓
|
|
194
|
+
Trigger: push to main, all PRs
|
|
195
|
+
Jobs: pnpm install → pnpm build → pnpm test
|
|
196
|
+
changeset presence check on PRs (warn only)
|
|
197
|
+
|
|
198
|
+
File: .github/workflows/release.yml ✓
|
|
199
|
+
Trigger: push to main
|
|
200
|
+
Jobs: changesets/action — creates "Version Packages" PR
|
|
201
|
+
when .changeset/ has entries; publishes to npm
|
|
202
|
+
when version PR is merged; GitHub releases auto-created
|
|
203
|
+
|
|
204
|
+
File: .github/workflows/publish.yml ✓
|
|
205
|
+
Trigger: manual (workflow_dispatch)
|
|
206
|
+
Jobs: emergency re-publish with optional dry-run mode
|
|
207
|
+
|
|
208
|
+
### Secrets required
|
|
209
|
+
NPM_TOKEN — same token as swiss-lib
|
|
210
|
+
CHANGESET_TOKEN — same token as swiss-lib
|
|
211
|
+
GITHUB_TOKEN — auto-provided
|
|
212
|
+
|
|
213
|
+
### Pending tasks
|
|
214
|
+
S-05 — Fix workspace:* deps so swite installs
|
|
215
|
+
standalone without swiss-lib monorepo.
|
|
216
|
+
MUST be done before first npm publish.
|
|
217
|
+
Current workaround: link: overrides in
|
|
218
|
+
consuming repos (alpine-erp).
|
|
219
|
+
|
|
220
|
+
### Known issues (to fix before publish)
|
|
221
|
+
- packages/cli has @swissjs/swite workspace:* dep
|
|
222
|
+
fixed to link:../../../swite for local builds
|
|
223
|
+
needs proper peer dep config for npm publish
|
|
224
|
+
- @swissjs/css Buffer conflict unrelated to swite
|
|
225
|
+
|
|
226
|
+
### Brand Rule
|
|
227
|
+
Swite is a global build tool.
|
|
228
|
+
Remove any regional labels from all docs.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Kibologic Foundational Decisions (locked 2026-03-01)
|
|
233
|
+
|
|
234
|
+
### Security & Repository Hardening
|
|
235
|
+
|
|
236
|
+
Signed commits
|
|
237
|
+
Required on main branch in all kibologic repos
|
|
238
|
+
Enforced via branch protection rules
|
|
239
|
+
No unsigned commits merged to main
|
|
240
|
+
|
|
241
|
+
SECURITY.md
|
|
242
|
+
Required in every public repo
|
|
243
|
+
Contains: security@kibologic.com contact
|
|
244
|
+
Disclosure timeline: 90 days
|
|
245
|
+
CVE process: GitHub Security Advisories
|
|
246
|
+
|
|
247
|
+
CODEOWNERS
|
|
248
|
+
Required in every repo
|
|
249
|
+
Founder owns everything initially
|
|
250
|
+
Format: * @themba-kibologic
|
|
251
|
+
Expandable as team grows
|
|
252
|
+
|
|
253
|
+
CodeQL scanning
|
|
254
|
+
Enabled on all PRs in all repos
|
|
255
|
+
GitHub Advanced Security
|
|
256
|
+
Blocks merge if critical vulnerability found
|
|
257
|
+
|
|
258
|
+
Pre-commit hooks
|
|
259
|
+
Tool: gitleaks
|
|
260
|
+
Blocks commits containing secrets/tokens
|
|
261
|
+
Applied to all repos on dev machines
|
|
262
|
+
Also runs in CI as second layer
|
|
263
|
+
|
|
264
|
+
### npm & Publishing Security
|
|
265
|
+
|
|
266
|
+
Automation tokens only for CI publish
|
|
267
|
+
Granular access tokens for human use
|
|
268
|
+
No local manual publish ever
|
|
269
|
+
2FA mandatory on npm org accounts
|
|
270
|
+
Unpublish policy: never after public release
|
|
271
|
+
Deprecation only via npm deprecate command
|
|
272
|
+
|
|
273
|
+
### GitHub Org Security
|
|
274
|
+
|
|
275
|
+
Dependabot enabled all repos
|
|
276
|
+
Secret scanning enabled all repos
|
|
277
|
+
CodeQL enabled all repos
|
|
278
|
+
Branch protection on main — all repos
|
|
279
|
+
Require 1 PR review
|
|
280
|
+
Require status checks to pass
|
|
281
|
+
Dismiss stale reviews
|
|
282
|
+
No admin bypass
|
|
283
|
+
CODEOWNERS required before merge
|
|
284
|
+
|
|
285
|
+
### License & Legal
|
|
286
|
+
|
|
287
|
+
BSL 1.1 on Alpine ERP and enterprise packages
|
|
288
|
+
Change date: 2029-12-31 → Apache 2.0
|
|
289
|
+
Trademark intent-to-use filed for:
|
|
290
|
+
SwissJS, Alpine ERP, Swite
|
|
291
|
+
CLA required for all external contributors
|
|
292
|
+
SECURITY.md in every public repo
|
|
293
|
+
BSL notice in repo root AND in every release
|
|
294
|
+
|
|
295
|
+
### Enterprise License Architecture
|
|
296
|
+
|
|
297
|
+
Format: signed JSON payload
|
|
298
|
+
Algorithm: ed25519
|
|
299
|
+
Private key: offline secure storage
|
|
300
|
+
Public key: embedded in backend only
|
|
301
|
+
Validation: backend only, never frontend only
|
|
302
|
+
Frontend role: feature visibility only
|
|
303
|
+
Offline validation: supported
|
|
304
|
+
Seat enforcement: hard block new user creation
|
|
305
|
+
Module enforcement: backend service layer guard
|
|
306
|
+
Self-hosted: license file in server env/config
|
|
307
|
+
SaaS: database-driven feature flags
|
|
308
|
+
|
|
309
|
+
### Deployment
|
|
310
|
+
|
|
311
|
+
Static sites: Cloudflare Pages
|
|
312
|
+
swissjs.dev, alpineerp.com, kibologic.com
|
|
313
|
+
SaaS backend: Fly.io or equivalent
|
|
314
|
+
Self-hosted: Docker Compose first
|
|
315
|
+
Official distribution: Docker image
|
|
316
|
+
Database: managed PostgreSQL provider
|
|
317
|
+
Kubernetes: not initially
|
|
318
|
+
|
|
319
|
+
### Domain & Email
|
|
320
|
+
|
|
321
|
+
All three domains on Cloudflare
|
|
322
|
+
SSL: Full strict
|
|
323
|
+
www → root redirect
|
|
324
|
+
HTTP → HTTPS
|
|
325
|
+
DNSSEC enabled
|
|
326
|
+
HSTS enabled
|
|
327
|
+
Email: Google Workspace or equivalent
|
|
328
|
+
Required addresses:
|
|
329
|
+
hello@kibologic.com
|
|
330
|
+
support@kibologic.com
|
|
331
|
+
legal@kibologic.com
|
|
332
|
+
SPF, DKIM, DMARC reject policy
|
|
333
|
+
|
|
334
|
+
### Community & Support
|
|
335
|
+
|
|
336
|
+
Initial channels: GitHub Issues only
|
|
337
|
+
Discord: after measurable traffic
|
|
338
|
+
Governance: founder-led
|
|
339
|
+
CONTRIBUTING.md required in all repos
|
|
340
|
+
Issue templates required in all repos
|
|
341
|
+
Public roadmap: high level only
|
|
342
|
+
Support: founder-led email/ticket
|
|
343
|
+
SLA: 24 business hours response
|
|
344
|
+
Private Slack for enterprise:
|
|
345
|
+
optional after revenue threshold
|
|
346
|
+
No 24/7 SLA initially
|
|
347
|
+
|
|
348
|
+
### Documentation
|
|
349
|
+
|
|
350
|
+
Primary author: founder
|
|
351
|
+
Tooling: VitePress or Starlight
|
|
352
|
+
Structure:
|
|
353
|
+
getting_started
|
|
354
|
+
core_concepts
|
|
355
|
+
api_reference
|
|
356
|
+
examples
|
|
357
|
+
Versioned docs: after v1
|
|
358
|
+
Separate docs for SwissJS and Alpine ERP
|
|
359
|
+
|
|
360
|
+
### Pricing Model
|
|
361
|
+
|
|
362
|
+
Model: open-core
|
|
363
|
+
Free: dashboard, users, settings, pos
|
|
364
|
+
Enterprise: finance, hr, inventory,
|
|
365
|
+
sales, procurement
|
|
366
|
+
Pricing dimensions: per user + per module
|
|
367
|
+
License validation: required (backend)
|
|
368
|
+
Self-hosted vs SaaS: different pricing
|
|
369
|
+
License key: signed ed25519 JSON
|
|
370
|
+
|
|
371
|
+
### Versioning & Release
|
|
372
|
+
|
|
373
|
+
Tool: Changesets (@changesets/cli)
|
|
374
|
+
Linked versioning for @swissjs/* core packages
|
|
375
|
+
Milestone-based releases
|
|
376
|
+
|
|
377
|
+
Milestones:
|
|
378
|
+
v0.1.0 — claim npm scopes, publish foundation
|
|
379
|
+
v0.2.0 — PostgreSQL + real data wiring
|
|
380
|
+
v0.3.0 — FastAPI auth complete
|
|
381
|
+
v0.4.0 — first enterprise module real data
|
|
382
|
+
v1.0.0 — first paying customer
|
|
383
|
+
|
|
384
|
+
Registry split:
|
|
385
|
+
npm public → @swissjs/*, @sws/*,
|
|
386
|
+
MIT @swiss-package/*
|
|
387
|
+
GitHub Pkg → BSL @swiss-package/*
|
|
388
|
+
GitHub only → alpine-erp (no npm)
|
|
389
|
+
|
|
390
|
+
### Brand Rule (non-negotiable)
|
|
391
|
+
|
|
392
|
+
Kibologic is a global company.
|
|
393
|
+
SwissJS, Alpine ERP, Swite are global products.
|
|
394
|
+
Remove all regional superlatives from every file.
|
|
395
|
+
"Africa's first" or any regional label is wrong.
|
|
396
|
+
Correct on sight in every session.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Manual Actions Pending
|
|
401
|
+
| ID | Action | Scope | Status |
|
|
402
|
+
|------|-----------------------------------------------------|--------------|---------|
|
|
403
|
+
| M-01 | Create @swissjs org on npmjs.com | npm | PENDING |
|
|
404
|
+
| M-03 | Add NPM_TOKEN secret to kibologic org GitHub | GitHub org | PENDING |
|
|
405
|
+
| M-04 | Add CHANGESET_TOKEN secret to kibologic org GitHub | GitHub org | PENDING |
|
|
406
|
+
| S-05 | Fix link: deps → proper semver deps before publish | swite repo | PENDING |
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Notes
|
|
411
|
+
- Python process manager must use Node `child_process.spawn` not `exec`
|
|
412
|
+
- Log streaming must be line-buffered — do not swallow partial lines
|
|
413
|
+
- `healthCheck` polling should use exponential backoff after 5 failed attempts
|
|
414
|
+
- `X-Internal-Token` is a shared secret between Node and Python — document in README
|
|
415
|
+
- Every session starts by reading this file. Every session ends by updating it.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## Session Log — 2026-05-19: Architectural Modernization Sprint
|
|
420
|
+
|
|
421
|
+
**Agent:** Long-term modernization, compiler evolution, and architectural stabilization agent.
|
|
422
|
+
|
|
423
|
+
### Identified Weaknesses (from prior sprint analysis)
|
|
424
|
+
- `import.meta.env` assignment is read-only — polyfill approach broken
|
|
425
|
+
- Import rewriter offset tracking unreliable (3 fallback layers signal broken primary logic)
|
|
426
|
+
- `/swiss-lib/` → `/swiss-packages/` fixup scattered across 7 places (symptom of unfixed upstream bug)
|
|
427
|
+
- HMR client JS embedded as TS string — maintenance trap (6 bugs found last sprint)
|
|
428
|
+
- `getDependencies()` duplicated between UIHandler/UIXHandler with empty importer
|
|
429
|
+
- CSS stripping with 4 overlapping regexes — edge cases produce broken output
|
|
430
|
+
- In-memory-only cache — cold start on every restart
|
|
431
|
+
- Emergency `@kibologic/*` path guessing in bare-import-resolver
|
|
432
|
+
|
|
433
|
+
### Work Executed This Session
|
|
434
|
+
|
|
435
|
+
#### fix/env-inline
|
|
436
|
+
**Problem:** `injectEnvPolyfill()` attempted `import.meta.env = switeEnv`. `import.meta` is read-only in ES modules — assignment silently fails or throws in strict environments. Apps using `import.meta.env.MODE` etc. get `undefined`.
|
|
437
|
+
**Decision:** Replace runtime injection with compile-time text replacement. At serve time, run a regex pass that replaces `import.meta.env.KEY` literals with their actual values from the loaded `.env` files. No import needed, no read-only assignment, works everywhere ES modules run.
|
|
438
|
+
**Files:** `src/env.ts`, `src/handlers/ui-handler.ts`, `src/handlers/uix-handler.ts`, `src/handlers/ts-handler.ts`
|
|
439
|
+
**Status:** FIXED
|
|
440
|
+
|
|
441
|
+
#### fix/import-rewriter
|
|
442
|
+
**Problem:** The offset-tracking approach (`let offset = 0; offset += ...`) accumulates errors when quote stripping/adding adjusts string lengths differently than expected. The 3-layer fallback (force-replace + final regex pass) exists because the primary logic is known to misfire.
|
|
443
|
+
**Decision:** Collect-then-apply-right-to-left. All replacements are gathered as `{start, end, replacement}` in original string coordinates (no offset needed). Sorted descending by `start`. Applied right-to-left so later positions are never shifted by earlier substitutions. Eliminates offset variable entirely.
|
|
444
|
+
**Files:** `src/import-rewriter.ts`
|
|
445
|
+
**Status:** FIXED
|
|
446
|
+
|
|
447
|
+
#### fix/swiss-lib-paths
|
|
448
|
+
**Problem:** `/swiss-lib/` → `/swiss-packages/` path fixup appeared in 7 places: ui-handler.ts ×3, uix-handler.ts ×3, import-rewriter.ts ×1 (inline) + 1 (final pass). Any new handler would need to add it again.
|
|
449
|
+
**Decision:** Extract to `src/utils/path-fixup.ts` with a single `fixSwissLibPaths(code)` function. Call it once in each handler, before passing to the import rewriter. Remove all inline fixup blocks from handlers and the duplicate pass from import-rewriter.ts.
|
|
450
|
+
**Note:** Root cause is still the compiler emitting wrong paths. This centralizes the workaround until the compiler is fixed at source.
|
|
451
|
+
**Files:** `src/utils/path-fixup.ts` (new), `src/handlers/ui-handler.ts`, `src/handlers/uix-handler.ts`, `src/import-rewriter.ts`
|
|
452
|
+
**Status:** FIXED
|
|
453
|
+
|
|
454
|
+
#### fix/hmr-client-file
|
|
455
|
+
**Problem:** `getClientScript()` in `src/hmr.ts` returns a plain JavaScript string (served directly to browsers) written inside a TypeScript file. Six TypeScript-specific syntax bugs were found last sprint. The string must be maintained as valid browser JS with no TS syntax — this is invisible to editors and linters.
|
|
456
|
+
**Decision:** Extract to `src/hmr-client.js`. This is a real JS file — editors lint it, syntax errors are caught immediately. Port and env are injected via `{{PORT}}` / `{{VERSION}}` template placeholders replaced at read time using `readFileSync`. The main `hmr.ts` reads it once at startup.
|
|
457
|
+
**Files:** `src/hmr-client.js` (new), `src/hmr.ts`
|
|
458
|
+
**Status:** FIXED
|
|
459
|
+
|
|
460
|
+
### Open Issues Carried Forward
|
|
461
|
+
- S-01 through S-04: Python service integration (not yet started)
|
|
462
|
+
- S-05: Fix link: deps → semver before publish
|
|
463
|
+
- In-memory cache: persistent disk cache deferred
|
|
464
|
+
- CSS modules: currently stripped, should return empty object
|
|
465
|
+
- HMR state preservation: full module hot-replacement state transfer deferred
|
|
466
|
+
- `@kibologic/*` emergency path guessing in bare-import-resolver: deferred (needs workspace resolver redesign)
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## Session Log — 2026-05-19 (continued): Context-resumed work
|
|
471
|
+
|
|
472
|
+
### Work Executed
|
|
473
|
+
|
|
474
|
+
#### fix/swiss-lib-paths (completed from prior session)
|
|
475
|
+
All changes written in prior session were verified (npx tsc --noEmit clean), committed, and shipped to main via development → staging → main.
|
|
476
|
+
|
|
477
|
+
#### fix/env-inline (completed from prior session)
|
|
478
|
+
Same status — context resumed, tsc clean, shipped.
|
|
479
|
+
|
|
480
|
+
#### fix/hmr-client-file (completed from prior session)
|
|
481
|
+
Same status — tsc clean, shipped.
|
|
482
|
+
|
|
483
|
+
### Open Issues Still Pending
|
|
484
|
+
- S-01 through S-04: Python service integration
|
|
485
|
+
- S-05: semver dep fix before publish
|
|
486
|
+
- Transform pipeline extraction (Lock 3 architecture)
|
|
487
|
+
- Resolver stratification (Lock 3)
|
|
488
|
+
- Python adapter interface (Lock 3)
|