create-flowdular 0.4.3 → 0.6.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/README.md +16 -10
- package/agent-template/.agents/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.agents/skills/auth-security-review/SKILL.md +2 -2
- package/agent-template/.agents/skills/bug-hunt/SKILL.md +1 -1
- package/agent-template/.agents/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.agents/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.agents/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.agents/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.agents/skills/module-new/SKILL.md +1 -1
- package/agent-template/.agents/skills/spec-interview/SKILL.md +20 -20
- package/agent-template/.agents/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.agents/skills/ux-design/SKILL.md +1 -1
- package/agent-template/.agents/skills/workflow-development/SKILL.md +95 -9
- package/agent-template/.ai/README.md +5 -3
- package/agent-template/.ai/agents/README.md +1 -1
- package/agent-template/.ai/agents/sandbox/agentic-engineer.md +1 -0
- package/agent-template/.ai/agents/sandbox/backend-engineer.md +1 -0
- package/agent-template/.ai/agents/sandbox/frontend-engineer.md +1 -0
- package/agent-template/.ai/blueprints/add-migration/README.md +1 -1
- package/agent-template/.ai/blueprints/add-migration/required-files.yaml +1 -1
- package/agent-template/.ai/blueprints/new-module/required-files.yaml +1 -1
- package/agent-template/.ai/examples/bad/client-imports-server/README.md +1 -1
- package/agent-template/.ai/examples/bad/missing-acl/README.md +1 -1
- package/agent-template/.ai/examples/bad/tenant-from-body/README.md +1 -1
- package/agent-template/.ai/guides/application-development.md +7 -5
- package/agent-template/.ai/platform-capabilities.md +9 -5
- package/agent-template/.ai/policies/capabilities.yaml +28 -12
- package/agent-template/.ai/policies/task-budgets.yaml +1 -1
- package/agent-template/.ai/rules/flowdular.md +3 -2
- package/agent-template/.ai/skills/README.md +1 -1
- package/agent-template/.ai/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.ai/skills/auth-security-review/SKILL.md +2 -2
- package/agent-template/.ai/skills/bug-hunt/SKILL.md +1 -1
- package/agent-template/.ai/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.ai/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.ai/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.ai/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.ai/skills/module-new/SKILL.md +1 -1
- package/agent-template/.ai/skills/spec-interview/SKILL.md +20 -20
- package/agent-template/.ai/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.ai/skills/ux-design/SKILL.md +1 -1
- package/agent-template/.ai/skills/workflow-development/SKILL.md +96 -10
- package/agent-template/.ai/subagents/module-executor.md +25 -0
- package/agent-template/.ai/subagents/reviewer.md +23 -0
- package/agent-template/.ai/subagents/spec-author.md +23 -0
- package/agent-template/.claude/agents/module-executor.md +22 -0
- package/agent-template/.claude/agents/reviewer.md +24 -0
- package/agent-template/.claude/agents/spec-author.md +20 -0
- package/agent-template/.claude/skills/agent-tool-design/SKILL.md +1 -1
- package/agent-template/.claude/skills/auth-security-review/SKILL.md +2 -2
- package/agent-template/.claude/skills/bug-hunt/SKILL.md +1 -1
- package/agent-template/.claude/skills/database-adapter/SKILL.md +5 -5
- package/agent-template/.claude/skills/database-adapter/references/first-run-and-matrix.md +2 -2
- package/agent-template/.claude/skills/deploy-operate/SKILL.md +1 -1
- package/agent-template/.claude/skills/migration-authoring/SKILL.md +4 -4
- package/agent-template/.claude/skills/module-new/SKILL.md +1 -1
- package/agent-template/.claude/skills/spec-interview/SKILL.md +20 -20
- package/agent-template/.claude/skills/test-hardening/SKILL.md +2 -2
- package/agent-template/.claude/skills/ux-design/SKILL.md +1 -1
- package/agent-template/.claude/skills/workflow-development/SKILL.md +95 -9
- package/agent-template/.codex/agents/module-executor.toml +17 -0
- package/agent-template/.codex/agents/reviewer.toml +14 -0
- package/agent-template/.codex/agents/spec-author.toml +15 -0
- package/agent-template/AGENTS.md +3 -2
- package/agent-template/CLAUDE.md +3 -2
- package/agent-template/docs/adr/0007-module-owned-agents.md +35 -1
- package/agent-template/docs/agent-contract.md +2 -2
- package/agent-template/docs/cli.md +24 -3
- package/agent-template/docs/configuration.md +59 -5
- package/agent-template/docs/database-adapters.md +20 -20
- package/agent-template/docs/design-system.md +3 -3
- package/agent-template/docs/getting-started.md +25 -32
- package/agent-template/docs/module-distribution.md +79 -86
- package/agent-template/docs/module-web-surfaces.md +9 -7
- package/agent-template/docs/modules.md +9 -1
- package/agent-template/docs/sandbox.md +117 -6
- package/agent-template/platform/scripts/build.mjs +7 -0
- package/agent-template/rulesync.jsonc +1 -1
- package/dist/bin.js +12 -6
- package/package.json +2 -2
- package/template/default/.env.example +10 -3
- package/template/default/.prettierignore +2 -0
- package/template/default/.vercelignore +8 -0
- package/template/default/README.md +26 -15
- package/template/default/_gitignore +3 -2
- package/template/default/infra/README.md +86 -65
- package/template/default/infra/docker/.env.example +66 -0
- package/template/default/infra/docker/Dockerfile +24 -10
- package/template/default/infra/docker/app-entrypoint.mjs +5 -0
- package/template/default/infra/docker/compose.yaml +105 -58
- package/template/default/infra/docker/database-urls.mjs +28 -0
- package/template/default/infra/docker/pitr.sh +177 -0
- package/template/default/infra/docker/postgres/10-roles.sh +16 -12
- package/template/default/infra/docker/start.mjs +402 -0
- package/template/default/infra/kubernetes/database-secret.example.yaml +3 -3
- package/template/default/infra/vercel/README.md +262 -0
- package/template/default/infra/vercel/build.mjs +214 -0
- package/template/default/infra/vercel/handler.mjs +100 -0
- package/template/default/modules/example/migrations/0001_example_core.up.sql +2 -2
- package/template/default/modules/example/module.json +1 -1
- package/template/default/modules/example/package.json +3 -3
- package/template/default/modules/example/spec/module.yaml +1 -1
- package/template/default/modules/example/src/services/migration.ts +2 -2
- package/template/default/modules/example/tests/module.test.ts +1 -1
- package/template/default/package.json +3 -2
- package/template/default/platform/index.html +7 -19
- package/template/default/platform/octane.config.ts +252 -156
- package/template/default/platform/package.json +5 -5
- package/template/default/platform/public/favicon.svg +1 -1
- package/template/default/platform/scripts/build.mjs +56 -0
- package/template/default/platform/scripts/dev.mjs +38 -0
- package/template/default/platform/src/App.tsrx +25 -1
- package/template/default/platform/src/generated/modules.server.ts +3 -0
- package/template/default/platform/src/server/database.ts +24 -0
- package/template/default/platform/src/server/runtime-role.ts +33 -0
- package/template/default/platform/src/server/setup/access.ts +160 -0
- package/template/default/platform/src/server/setup/adapters.ts +554 -0
- package/template/default/platform/src/server/setup/environment.ts +154 -0
- package/template/default/platform/src/server/setup/gate.ts +84 -0
- package/template/default/platform/src/server/setup/index.ts +181 -0
- package/template/default/platform/src/server/setup/modules.ts +123 -0
- package/template/default/platform/src/server/setup/page.ts +497 -0
- package/template/default/platform/src/server/setup/routes.ts +787 -0
- package/template/default/platform/src/server/setup/sanitize.ts +111 -0
- package/template/default/platform/src/server/setup/seed.ts +145 -0
- package/template/default/platform/src/server/setup/token.ts +79 -0
- package/template/default/platform/src/server/worker-tick.ts +193 -0
- package/template/default/platform/src/server/workspace-root.ts +16 -0
- package/template/default/render.yaml +70 -0
- package/template/default/vercel.json +5 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
|
-
Run Flowdular on your machine,
|
|
3
|
+
Run Flowdular on your machine, create a workspace, and sign in.
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
@@ -19,48 +19,40 @@ pnpm flowdular doctor
|
|
|
19
19
|
`doctor` reports workspace health (configuration, enabled modules, generated
|
|
20
20
|
composition, guardrail files). Add `--json` for a machine-readable envelope.
|
|
21
21
|
|
|
22
|
-
##
|
|
23
|
-
|
|
24
|
-
`pnpm flowdular setup` opens an interactive wizard. Choose a local demo, configure PostgreSQL, or check the existing configuration. Local initialization requires confirmation and a stopped application.
|
|
25
|
-
|
|
26
|
-
For scripts and CI, `setup quick` is a destructive local reset. It prints its full plan first and
|
|
27
|
-
writes only after a typed confirmation:
|
|
22
|
+
## Run the platform
|
|
28
23
|
|
|
29
24
|
```bash
|
|
30
|
-
pnpm
|
|
31
|
-
pnpm flowdular setup quick --apply --confirm reset-local-auth # resets and seeds
|
|
25
|
+
pnpm dev
|
|
32
26
|
```
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
On the first run, open [localhost:4310/setup](http://localhost:4310/setup).
|
|
29
|
+
Enter the one-time token from the terminal, then create your
|
|
30
|
+
workspace and owner account. Embedded PostgreSQL is already configured. Restart
|
|
31
|
+
`pnpm dev` after setup and sign in with that account.
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
Vite HMR covers TSRX, TypeScript and styles. The launcher keeps tool warnings
|
|
34
|
+
quiet; use `pnpm dev -- --verbose` for full diagnostics. `pnpm dev` runs
|
|
35
|
+
`module sync` first, so a composition change is picked up without a manual
|
|
36
|
+
step. The session lives in an HttpOnly cookie and carries the scopes of the
|
|
37
|
+
selected tenant membership. A bookmark pointing at another workspace you
|
|
38
|
+
belong to switches the session on load.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| `admin@example.com` | `Owner!23456789` | Owner of both demo tenants |
|
|
42
|
-
| `user@example.com` | `Member!2345678` | Reduced scope member |
|
|
40
|
+
`Development` navigation is visible only to tenant owners; server permissions
|
|
41
|
+
stay authoritative either way.
|
|
43
42
|
|
|
44
|
-
##
|
|
43
|
+
## Optional local demo reset
|
|
44
|
+
|
|
45
|
+
`pnpm flowdular setup quick` resets local authentication data and seeds two
|
|
46
|
+
demo workspaces. It is for development or test databases only. Stop `pnpm dev`
|
|
47
|
+
and review the dry-run plan before applying it:
|
|
45
48
|
|
|
46
49
|
```bash
|
|
47
|
-
pnpm
|
|
50
|
+
pnpm flowdular setup quick # dry run, prints the plan
|
|
51
|
+
pnpm flowdular setup quick --apply --confirm reset-local-auth # resets and seeds
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
diagnostics. `pnpm dev` runs `module sync` first, so a composition change is
|
|
53
|
-
picked up without a manual step.
|
|
54
|
-
|
|
55
|
-
The first visit opens the `auth.core` sign-in flow. The session lives in an
|
|
56
|
-
HttpOnly cookie and carries the scopes of the selected tenant membership. On a
|
|
57
|
-
clean database the sign-up wizard is available: workspace name plus a unique
|
|
58
|
-
workspace id (the first URL segment, `/{workspace}/{view}`), then the
|
|
59
|
-
administrator account, then an optional email confirmation step. A bookmark
|
|
60
|
-
pointing at another workspace you belong to switches the session on load.
|
|
61
|
-
|
|
62
|
-
`Development` navigation is visible only to tenant owners; server permissions
|
|
63
|
-
stay authoritative either way.
|
|
54
|
+
The demo logins are `admin@example.com` / `Owner!23456789` (owner) and
|
|
55
|
+
`user@example.com` / `Member!2345678` (member).
|
|
64
56
|
|
|
65
57
|
## Where local state lives
|
|
66
58
|
|
|
@@ -69,6 +61,7 @@ module shares one embedded PostgreSQL in `.flowdular/data/pglite`, which
|
|
|
69
61
|
`FD_DATABASE_PGLITE_DIRECTORY` can redirect. Point `FD_DATABASE_ADAPTER` at
|
|
70
62
|
`postgresql` and give it `FD_DATABASE_URL` to run against a real server instead.
|
|
71
63
|
See [configuration.md](configuration.md).
|
|
64
|
+
Workspaces from Flowdular 0.5 or earlier: see [flowdular-rename.md](https://github.com/flowdular/flowdular/blob/main/docs/flowdular-rename.md).
|
|
72
65
|
|
|
73
66
|
## Migrating preserved state from `.octane-erp`
|
|
74
67
|
|
|
@@ -1,103 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Module Studio
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Module Studio uses one reviewable plan for a module source change. A platform
|
|
4
|
+
checkout owns its sources in `flowdular.module-sources.json`, its exact plans in
|
|
5
|
+
`module-plans/<sha256>.json`, and installed source hashes in
|
|
6
|
+
`flowdular.modules.lock.json`. Commit these files with the application when
|
|
7
|
+
they change. A catalog can be a local JSON file or an HTTPS URL. A Git source
|
|
8
|
+
names a repository and a full commit, and may itself be local or HTTPS. No
|
|
9
|
+
publisher or repository name is built into the installer.
|
|
7
10
|
|
|
8
11
|
```sh
|
|
9
|
-
pnpm flowdular module
|
|
10
|
-
pnpm flowdular module
|
|
11
|
-
|
|
12
|
-
pnpm flowdular module
|
|
12
|
+
pnpm flowdular module source add community https://modules.example/registry/index.json --apply
|
|
13
|
+
pnpm flowdular module source add team https://github.com/acme/modules.git \
|
|
14
|
+
--git-commit <40-character-commit> --catalog-path registry/index.json --apply
|
|
15
|
+
pnpm flowdular module source add local ./registry/index.json --apply
|
|
16
|
+
pnpm flowdular module source list
|
|
17
|
+
pnpm flowdular module search expenses --source community
|
|
18
|
+
pnpm flowdular module plan expenses.core@1.2.0 --source community --apply
|
|
19
|
+
pnpm flowdular module plan show <plan-id>
|
|
20
|
+
pnpm flowdular module apply <plan-id> --apply
|
|
13
21
|
pnpm flowdular module enable expenses.core --apply
|
|
14
|
-
pnpm
|
|
22
|
+
pnpm build
|
|
15
23
|
```
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
`
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
`source add`, `plan`, and `apply` preview their work unless `--apply` is present.
|
|
26
|
+
With exactly one configured source, `--source` may be omitted. `module plan
|
|
27
|
+
list` shows saved plans; `module plan remove <plan-id> --apply` deletes an
|
|
28
|
+
obsolete plan. At most 32 plans may exist at once, with 4 MiB per plan and
|
|
29
|
+
8 MiB in total. A plan records the selected
|
|
30
|
+
releases, artifact SHA-256, Git commit where applicable, dependency closure,
|
|
31
|
+
requested permissions, migration file hashes, and server/client build impact.
|
|
32
|
+
Its ID hashes the plan content. Applying it refuses changed workspace module
|
|
33
|
+
manifests or a changed install lock and verifies every artifact again. If the
|
|
34
|
+
source is no longer available, regenerate or provide it again; the plan does
|
|
35
|
+
not contain executable source bytes.
|
|
36
|
+
|
|
37
|
+
Installation copies reviewed source into a configured module root and writes
|
|
38
|
+
the install lock. It does not run downloaded scripts, npm install, migrations,
|
|
39
|
+
or permission grants. `module enable --apply` links the package, regenerates
|
|
40
|
+
composition and follows the platform's scope grant process. Rebuild and
|
|
41
|
+
restart the application to serve new code. A deployed container shows plans
|
|
42
|
+
and module state in Administration, Module Studio; it never writes its own code.
|
|
43
|
+
For creating or changing your own module, the same view links to Sandbox when
|
|
44
|
+
`sandbox.core` is active. Sandbox keeps the approved spec hash, gate and PR
|
|
45
|
+
checks, and delivers to the workspace or its configured Git repository.
|
|
37
46
|
|
|
38
47
|
## Trust and recovery
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
49
|
+
Only a configured host CLI resolves sources. Sandbox specialists do not gain
|
|
50
|
+
network, Git, database or filesystem permissions from a source entry. HTTPS
|
|
51
|
+
downloads reject redirects and have time and size limits. HTTPS artifacts must
|
|
52
|
+
use the catalog origin and a path containing their declared source commit.
|
|
53
|
+
The artifact digest is verified after download. Git checkouts verify their full
|
|
54
|
+
commit. Catalogs and artifacts are bounded; paths, manifests, package scripts,
|
|
55
|
+
review evidence and approved specs are checked before a plan is saved. A
|
|
56
|
+
checksum identifies bytes but does not certify a publisher, so review the
|
|
57
|
+
source and permissions before `module apply` and `module enable`.
|
|
58
|
+
|
|
59
|
+
Updates use `module plan <id[@version]> --source <name> --update --apply`.
|
|
60
|
+
The installer refuses local changes, changed historical migrations and
|
|
61
|
+
downgrades. `module validate --locked` checks installed file hashes. Installs
|
|
62
|
+
use an exclusive transaction directory; after a process crash, run `module
|
|
63
|
+
recover` and then `module recover --apply`. Recovery restores source and lock
|
|
64
|
+
state, not database migrations. Source-list edits use a separate
|
|
65
|
+
`flowdular.module-sources.json.lock` directory. If a host process crashes
|
|
66
|
+
during that short write, confirm no other source command is running and remove
|
|
67
|
+
that stale directory before retrying.
|
|
68
|
+
Plan writes use the same atomic pattern and a `module-plans.lock` directory.
|
|
69
|
+
After a crash, confirm the writer has stopped and remove a stale plan lock
|
|
70
|
+
before retrying; no partial plan is published.
|
|
71
|
+
|
|
72
|
+
Scripts that called `module install` or `module update` with `--registry` must
|
|
73
|
+
add that catalog as a named source, save a plan, and apply its ID. An existing
|
|
74
|
+
`flowdular.modules.lock.json` remains the installed-source record, so an
|
|
75
|
+
already managed module can use `module plan <id> --update --apply` for its next
|
|
76
|
+
release. No direct registry installation path remains.
|
|
77
|
+
Automation that imported `installModule` from `flowdular/distribution` must use
|
|
78
|
+
the host CLI plan and apply commands; that direct install export was removed.
|
|
79
|
+
|
|
80
|
+
The old `official-modules` Sandbox delivery target was removed. Change
|
|
81
|
+
`sandbox.delivery.targets` to `workspace` or `git-pr`; `git-pr` points to the
|
|
82
|
+
platform repository configured in `flowdular.json`. A catalog publisher can
|
|
83
|
+
use any Git repository and publish immutable artifacts independently. Historical
|
|
84
|
+
review and RFC documents retain the old project name as provenance.
|
|
61
85
|
|
|
62
86
|
## SDK publication and consumer checks
|
|
63
87
|
|
|
64
88
|
```sh
|
|
65
89
|
pnpm release:pack
|
|
66
90
|
pnpm release:smoke
|
|
67
|
-
# Also install and test actual source artifacts from the official repo:
|
|
68
|
-
node scripts/smoke-sdk.mjs release-artifacts/sdk /path/to/official-modules/registry/local-index.json
|
|
69
91
|
```
|
|
70
92
|
|
|
71
|
-
`release-artifacts/sdk/sdk.json` lists
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
artifacts outside runtime state directories; creating both `.flowdular` and legacy
|
|
76
|
-
`.coreloom` state would correctly stop the application.
|
|
77
|
-
|
|
78
|
-
The smoke test creates a separate project and resolves SDK dependencies from
|
|
79
|
-
packed artifacts, without aliases or symlinks into core sources. With a module
|
|
80
|
-
catalog it installs all module source artifacts, enables their source composition,
|
|
81
|
-
checks the lock, typechecks and executes the consumer's tests. Its composition
|
|
82
|
-
check does not grant tenant scopes; auth CLI tests cover that separate boundary.
|
|
83
|
-
|
|
84
|
-
Sandbox examples use `.ai/references/catalog`, generated from a reviewed official
|
|
85
|
-
artifact. `pnpm reference:check` verifies every file against the pinned provenance
|
|
86
|
-
record. Do not edit the generated reference. To update it, build the CLI and run
|
|
87
|
-
`scripts/module-reference.mjs` with `--artifact`, `--sha256`, `--source-commit` and
|
|
88
|
-
`--apply`. Skills and sandbox preparation refer to that offline snapshot.
|
|
89
|
-
|
|
90
|
-
`pnpm release:publish` previews the exact publication set after validating every
|
|
91
|
-
artifact digest. The operator can then use `pnpm release:publish --apply` after npm
|
|
92
|
-
authentication. It skips already-published identical tarballs and stops if a
|
|
93
|
-
version exists with different bytes. No npm publication is performed by packing,
|
|
94
|
-
smoke testing or the default publication preview.
|
|
95
|
-
|
|
96
|
-
The `SDK consumer smoke` workflow (`.github/workflows/sdk-release.yml`, job
|
|
97
|
-
`consumer`) runs the pack and the smoke on every pull request and push to main
|
|
98
|
-
that touches `packages`, `modules` or `scripts`. It never publishes: its token
|
|
99
|
-
can only read the repository, and the packed tarballs are kept as an Actions
|
|
100
|
-
artifact only after a merge to main. `pnpm verify` is not repeated there, the
|
|
101
|
-
CI workflow owns it.
|
|
102
|
-
|
|
103
|
-
The SDK is assembled from private internal workspaces. Import UI from `@flowdular/sdk/ui` and styles from `@flowdular/sdk/ui/styles`; use `@flowdular/sdk/server`, `client`, `contracts` or `modules/<name>` for other surfaces. There is no root SDK barrel, so browser imports do not load server entrypoints. See [npm publication](https://github.com/flowdular/flowdular/blob/main/docs/npm-publication.md).
|
|
93
|
+
`release-artifacts/sdk/sdk.json` lists the SDK, CLI, project generator and
|
|
94
|
+
Sandbox tarballs with SHA-256 digests. Publication is separate from packing
|
|
95
|
+
and smoke tests. The project generator and SDK must be released together so a
|
|
96
|
+
new application's module tooling sees the same contracts.
|
|
@@ -140,13 +140,15 @@ in front of it, as the bundled Node server does.
|
|
|
140
140
|
### Backoffice address
|
|
141
141
|
|
|
142
142
|
The first-run setup includes **Backoffice address**, defaulting to `/app` (or the
|
|
143
|
-
installation's configured default).
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
installation's configured default). When choosing a database in the wizard, an
|
|
144
|
+
operator can choose `/backoffice` to leave `/` available for a storefront. Setup
|
|
145
|
+
validates the address, includes it in the review, and writes
|
|
146
|
+
`FD_APPLICATION_PATH=/backoffice` alongside the database settings. Restart after
|
|
147
|
+
setup; no client rebuild is needed. When the database is already configured by
|
|
148
|
+
the deployment, the wizard skips that step and the deployment's
|
|
149
|
+
`FD_APPLICATION_PATH` controls the address. A read-only deployment must store
|
|
150
|
+
new settings in its environment before restart. Setup never echoes connection
|
|
151
|
+
secrets back to the browser.
|
|
150
152
|
|
|
151
153
|
For configuration managed in source control, add:
|
|
152
154
|
|
|
@@ -65,6 +65,12 @@ at least one entity (`SPEC_ACTION_PERMISSION_UNKNOWN`, `SPEC_ENTITY_UNKNOWN`,
|
|
|
65
65
|
`SPEC_DUPLICATE_ID`). A client without a list screen, or a stored entity with no
|
|
66
66
|
tenant-unique field, is a warning.
|
|
67
67
|
|
|
68
|
+
An action may not declare `risk: external`. A module never calls another system
|
|
69
|
+
directly: the harness and the CLI runner both refuse an external action, so the
|
|
70
|
+
specification catches it here instead of at delivery
|
|
71
|
+
(`SPEC_ACTION_RISK_UNSUPPORTED`). Model the effect as a connector definition plus
|
|
72
|
+
an adapter, or lower the risk.
|
|
73
|
+
|
|
68
74
|
The three optional sections have checks of their own. `research.evidenceOwner`
|
|
69
75
|
and `templates[].inputEntity` must name an entity (`SPEC_ENTITY_UNKNOWN`). An
|
|
70
76
|
adapter id must start with the module id (`SPEC_ADAPTER_ID_NAMESPACE`); a source
|
|
@@ -216,7 +222,9 @@ dependents, which the bump command does. `module validate` reports
|
|
|
216
222
|
`PLATFORM_API_MISSING` when a manifest lacks `platformApi`.
|
|
217
223
|
|
|
218
224
|
`platformApi` is the range of the platform contract the module compiles against
|
|
219
|
-
(`^0.
|
|
225
|
+
(`^0.2.0`). Module sync and install refuse a manifest without one, and a range
|
|
226
|
+
that also admits a version before the platform's current minor line, such as
|
|
227
|
+
`*` or `>=0.1.0`. The contract surface is pinned in
|
|
220
228
|
`packages/kernel/platform-api.snapshot.d.ts`; a change to it without a
|
|
221
229
|
`PLATFORM_API_VERSION` bump fails `pnpm verify`. `module search --compatible`
|
|
222
230
|
lists only releases whose range accepts the running platform.
|
|
@@ -12,12 +12,85 @@ Full documentation lives with the package:
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
pnpm sandbox # from this repository
|
|
15
|
-
npx @flowdular/sandbox # from any Flowdular workspace
|
|
15
|
+
npx @flowdular/sandbox # from any Flowdular workspace, or from an empty one
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
the
|
|
18
|
+
In an empty directory, the command creates a standalone Flowdular application,
|
|
19
|
+
installs its dependencies, starts it with a local embedded PostgreSQL database,
|
|
20
|
+
prepares the sandbox credential and serves the dashboard on
|
|
21
|
+
`http://127.0.0.1:4320`. You can then describe the module in the dashboard.
|
|
22
|
+
|
|
23
|
+
## Start with nothing installed
|
|
24
|
+
|
|
25
|
+
There is no checkout step.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
mkdir acme-erp && cd acme-erp
|
|
29
|
+
npx @flowdular/sandbox
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The launcher uses `create-flowdular` at the sandbox package's exact version,
|
|
33
|
+
installs the generated application and makes its first local Git commit. It
|
|
34
|
+
reuses that workspace on later runs. The application lands in `./flowdular`
|
|
35
|
+
unless `--workspace <path>` names another directory. No remote is created until
|
|
36
|
+
you choose one.
|
|
37
|
+
|
|
38
|
+
The repository dialog can create a private GitHub repository or connect an
|
|
39
|
+
empty one after showing the initial push plan. If creation is interrupted, the
|
|
40
|
+
same dialog shows the pending attempt. You can resume it or discard its local
|
|
41
|
+
record after GitHub returns an authenticated 404. A private repository hidden
|
|
42
|
+
from the current account may also return 404, so check GitHub if creation may
|
|
43
|
+
have succeeded.
|
|
44
|
+
|
|
45
|
+
To work on an existing platform repository, run
|
|
46
|
+
`npx @flowdular/sandbox --connect <git-url>` and optionally `--branch <name>`.
|
|
47
|
+
The launcher clones into a new directory, checks `flowdular.json` and the
|
|
48
|
+
committed pnpm lockfile, then installs dependencies. Run from an existing
|
|
49
|
+
Flowdular checkout to reuse it without cloning. `--no-bootstrap` refuses to
|
|
50
|
+
create an application. The older `--repository` and pinned `--ref` options
|
|
51
|
+
remain available when you deliberately want a checkout of the Flowdular core
|
|
52
|
+
repository.
|
|
53
|
+
|
|
54
|
+
The launcher refuses to create or clone into a directory containing unrelated
|
|
55
|
+
files. For application generation, Git and pnpm are checked before files are
|
|
56
|
+
written.
|
|
57
|
+
|
|
58
|
+
An application already serving on the platform port is left alone, and no
|
|
59
|
+
credential is prepared for it. `--platform` and `--platform-port` say otherwise
|
|
60
|
+
explicitly; `--no-platform` never starts one.
|
|
61
|
+
|
|
62
|
+
## The credential is prepared, not pasted
|
|
63
|
+
|
|
64
|
+
A business user used to sign in to the application, create an API token with
|
|
65
|
+
three scopes, paste it into the sandbox and grant that account sandbox access
|
|
66
|
+
before describing anything. None of those is a business decision, so the
|
|
67
|
+
application does them during its own boot when the launcher asks, and the
|
|
68
|
+
launcher collects the result.
|
|
69
|
+
|
|
70
|
+
- It runs only when the launcher started the application, so an application
|
|
71
|
+
someone else owns is never asked to create an account.
|
|
72
|
+
- It reuses an existing workspace and account rather than replacing them, and
|
|
73
|
+
mints exactly one token for the life of the deployment.
|
|
74
|
+
- The token carries the four sandbox scopes and nothing else.
|
|
75
|
+
- It is written to a `0600` file that the launcher seals into its own
|
|
76
|
+
configuration and deletes. It is never printed, so it reaches no terminal, log
|
|
77
|
+
or transcript.
|
|
78
|
+
- Token management over HTTP is unchanged: `POST /api/auth/api-tokens` still
|
|
79
|
+
refuses a machine credential, and no route was added for this.
|
|
80
|
+
|
|
81
|
+
The account is `sandbox-operator@example.com` in a `sandbox` workspace, with a
|
|
82
|
+
password nobody has. It exists to hold the grant.
|
|
83
|
+
|
|
84
|
+
**A failed provision never stops the application.** It is a convenience for a
|
|
85
|
+
local operator, and an application that will not serve because a sandbox account
|
|
86
|
+
could not be created is worse than one that serves and reports the problem.
|
|
87
|
+
|
|
88
|
+
For a remote deployment, or a sandbox started some other way, the dashboard says
|
|
89
|
+
what is missing. One command fixes it:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pnpm flowdular sandbox provision --apply
|
|
93
|
+
```
|
|
21
94
|
|
|
22
95
|
## Connect it to a running application
|
|
23
96
|
|
|
@@ -29,6 +102,8 @@ security a deployment has, and it is thrown away with the session.
|
|
|
29
102
|
1. In the application, open Administration, API tokens, and issue a token with
|
|
30
103
|
`sandbox.access.use` plus the read scopes the preview should see. Add
|
|
31
104
|
`sandbox.preview.data` for live data and `sandbox.modules.eject` for eject.
|
|
105
|
+
Enable token writes so the sandbox can record sessions, eject modules and
|
|
106
|
+
publish the application repository when you request it.
|
|
32
107
|
2. Grant sandbox access to the account, in the app under Development, Sandbox,
|
|
33
108
|
or from the CLI:
|
|
34
109
|
|
|
@@ -38,9 +113,11 @@ pnpm flowdular sandbox access --tenant operations-demo
|
|
|
38
113
|
```
|
|
39
114
|
|
|
40
115
|
3. Paste the token and the application address into the sandbox connect screen.
|
|
116
|
+
The same screen asks for a model provider and key, unless the workspace
|
|
117
|
+
already carries one, in which case it names the variable it adopted.
|
|
41
118
|
|
|
42
|
-
The token
|
|
43
|
-
returned to the browser. The application may run anywhere: locally on
|
|
119
|
+
The token and the model key are encrypted at rest under
|
|
120
|
+
`.flowdular/sandbox/secret.key` and are never returned to the browser. The application may run anywhere: locally on
|
|
44
121
|
`http://127.0.0.1:4310` or a deployment.
|
|
45
122
|
|
|
46
123
|
## Modes
|
|
@@ -54,6 +131,25 @@ A non-loopback `--host` forces `self-hosted`. A sandbox that cannot prove it is
|
|
|
54
131
|
loopback never offers a local binary, because a local binary carries the
|
|
55
132
|
operator's own login.
|
|
56
133
|
|
|
134
|
+
The bring-your-own-key driver takes its credential from the sandbox model
|
|
135
|
+
settings, or, when none is saved there, from `ANTHROPIC_API_KEY`,
|
|
136
|
+
`OPENAI_API_KEY`, `AZURE_API_KEY` or `AI_GATEWAY_API_KEY` in the environment or
|
|
137
|
+
the workspace `.env`. A scaffolded application ships the first of those as an
|
|
138
|
+
empty placeholder, so pasting a key is the whole setup.
|
|
139
|
+
|
|
140
|
+
## Typed decisions
|
|
141
|
+
|
|
142
|
+
The brief classification the planner performs (which module, spans several,
|
|
143
|
+
which specialist starts) can be answered by a decision provider instead of a
|
|
144
|
+
coding-agent turn. It is off by default, turned on per sandbox with
|
|
145
|
+
`decisionsEnabled` through `POST /sandbox/api/config`, and takes its credential
|
|
146
|
+
from the sandbox configuration or `TYPESAFE_API_KEY` in the environment or the
|
|
147
|
+
workspace `.env`. Answers below their confidence thresholds, a brief that spans
|
|
148
|
+
modules, and any provider failure all fall back to the workspace rules and the
|
|
149
|
+
planner turn. Implementation writing stays with the coding agent: a decision
|
|
150
|
+
provider generates no text and drives no tools. See
|
|
151
|
+
[`packages/sandbox/README.md`](https://github.com/flowdular/flowdular/blob/main/packages/sandbox/README.md) for the settings.
|
|
152
|
+
|
|
57
153
|
## How a session works
|
|
58
154
|
|
|
59
155
|
A planner names the modules the brief touches and the first specialist role.
|
|
@@ -147,6 +243,21 @@ commits the same change on a branch and opens a pull request; the operator's
|
|
|
147
243
|
working tree and index stay untouched because the work happens in a detached
|
|
148
244
|
worktree under `.flowdular/sandbox/worktrees/<session id>`, removed afterwards.
|
|
149
245
|
|
|
246
|
+
For an application generated by the sandbox, open **GitHub settings** and then
|
|
247
|
+
**Set up repository**. Choose an existing empty GitHub repository or
|
|
248
|
+
create a new private one. The sandbox shows the repository, local commit and
|
|
249
|
+
target branch for review before the operator confirms the first push. It then
|
|
250
|
+
adds a local `app` remote, pushes `main` without rewriting remote history and
|
|
251
|
+
configures GitHub delivery to use that remote. A repository that already has
|
|
252
|
+
commits should be opened with `--connect` when launching the sandbox. GitHub
|
|
253
|
+
CLI authentication or a token saved in GitHub settings is needed for creating
|
|
254
|
+
and pushing; the setup action also requires `sandbox.modules.eject`.
|
|
255
|
+
|
|
256
|
+
After the module specification is approved and the gates pass, choose the
|
|
257
|
+
`git-pr` delivery target to push a branch and open its review. The sandbox does
|
|
258
|
+
not approve a specification or push module code merely because a repository
|
|
259
|
+
was connected.
|
|
260
|
+
|
|
150
261
|
### Configuration
|
|
151
262
|
|
|
152
263
|
Project settings live in `flowdular.json` under `sandbox.delivery`, read at
|
|
@@ -7,6 +7,13 @@ import { join } from 'node:path';
|
|
|
7
7
|
const stateDirectory = mkdtempSync(join(tmpdir(), 'flowdular-build-'));
|
|
8
8
|
const buildSecret = () => randomBytes(32).toString('base64');
|
|
9
9
|
|
|
10
|
+
/* Vite clears its output trees, but can leave hidden runtime state at the
|
|
11
|
+
dist root. A prior preview must never become part of the next bundle. */
|
|
12
|
+
rmSync(join(import.meta.dirname, '..', 'dist'), {
|
|
13
|
+
recursive: true,
|
|
14
|
+
force: true,
|
|
15
|
+
});
|
|
16
|
+
|
|
10
17
|
/* The Octane plugin evaluates the server composition while bundling it. Give
|
|
11
18
|
that build-time process isolated state and ephemeral keys, without using deployment database settings or encryption keys. The emitted server still reads its real
|
|
12
19
|
production environment when it starts. */
|
package/dist/bin.js
CHANGED
|
@@ -294,7 +294,6 @@ function nextSteps(input) {
|
|
|
294
294
|
return [
|
|
295
295
|
`cd ${input.directory}`,
|
|
296
296
|
...input.installed ? [] : [`${input.packageManager} install`],
|
|
297
|
-
runScript(input.packageManager, "flowdular", "setup"),
|
|
298
297
|
runScript(input.packageManager, "dev")
|
|
299
298
|
];
|
|
300
299
|
}
|
|
@@ -303,8 +302,7 @@ function renderNextSteps(input, color = false) {
|
|
|
303
302
|
const labels = [
|
|
304
303
|
"Open your project",
|
|
305
304
|
...input.installed ? [] : ["Install dependencies"],
|
|
306
|
-
"
|
|
307
|
-
"Start your app"
|
|
305
|
+
"Start your app and first-run setup"
|
|
308
306
|
];
|
|
309
307
|
return [
|
|
310
308
|
"",
|
|
@@ -322,9 +320,8 @@ function renderNextSteps(input, color = false) {
|
|
|
322
320
|
` ${paint("Build a module by chat", "dim")} ${paint(runScript(input.packageManager, "sandbox"), "bold")}`,
|
|
323
321
|
` ${paint("Agent guidance", "dim")} AGENTS.md, CLAUDE.md, .ai/skills`,
|
|
324
322
|
"",
|
|
325
|
-
` ${paint("
|
|
326
|
-
` ${paint("
|
|
327
|
-
` ${paint("Demo account is created only with local demo setup.", "dim")}`,
|
|
323
|
+
` ${paint("Setup URL", "dim")} ${paint(`${DEV_URL}/setup`, "cyan")}`,
|
|
324
|
+
` ${paint("Setup opens in a browser when available. Use the printed token, then choose your workspace owner.", "dim")}`,
|
|
328
325
|
""
|
|
329
326
|
].join("\n");
|
|
330
327
|
}
|
|
@@ -386,6 +383,15 @@ function renderEnvironmentFile(secrets) {
|
|
|
386
383
|
"",
|
|
387
384
|
"# 32 byte keys, generated once for this app; MFA uses base64url.",
|
|
388
385
|
...SECRET_KEYS.map((key) => `${key}=${secrets[key]}`),
|
|
386
|
+
"",
|
|
387
|
+
"# Model key for the chat-first sandbox (pnpm sandbox). Paste one here and",
|
|
388
|
+
"# the sandbox offers that model on the next start, with no further setup.",
|
|
389
|
+
"# OPENAI_API_KEY, AZURE_API_KEY and AI_GATEWAY_API_KEY are read the same",
|
|
390
|
+
"# way, with the model chosen in the sandbox model settings. A variable",
|
|
391
|
+
"# exported in the shell wins over this file. The application's own agents",
|
|
392
|
+
"# keep their credentials in the workspace vault instead: open",
|
|
393
|
+
"# Administration, AI providers.",
|
|
394
|
+
"ANTHROPIC_API_KEY=",
|
|
389
395
|
""
|
|
390
396
|
].join("\n");
|
|
391
397
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-flowdular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Scaffold a Flowdular application: the platform, one example module and the secrets a fresh install needs.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/Flowdular/flowdular.git",
|
|
10
10
|
"directory": "packages/create-flowdular"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://flowdular.com",
|
|
@@ -13,9 +13,9 @@ FD_PORT=3000
|
|
|
13
13
|
# every tenant table forces actually binds the app, and the background role
|
|
14
14
|
# serves the cross-tenant scheduler poll. pglite is refused in production.
|
|
15
15
|
FD_DATABASE_ADAPTER=postgresql
|
|
16
|
-
FD_DATABASE_URL=postgresql://
|
|
17
|
-
FD_DATABASE_MIGRATOR_URL=postgresql://
|
|
18
|
-
FD_DATABASE_BACKGROUND_URL=postgresql://
|
|
16
|
+
FD_DATABASE_URL=postgresql://flowdular_runtime:REPLACE_ME@postgres:5432/flowdular
|
|
17
|
+
FD_DATABASE_MIGRATOR_URL=postgresql://flowdular_migrator:REPLACE_ME@postgres:5432/flowdular
|
|
18
|
+
FD_DATABASE_BACKGROUND_URL=postgresql://flowdular_background:REPLACE_ME@postgres:5432/flowdular
|
|
19
19
|
FD_DATABASE_TLS=verify-full
|
|
20
20
|
FD_DATABASE_TLS_CA_FILE=/tls/server.crt
|
|
21
21
|
|
|
@@ -91,6 +91,13 @@ FD_DATABASE_MIGRATOR_PASSWORD=
|
|
|
91
91
|
FD_DATABASE_RUNTIME_PASSWORD=
|
|
92
92
|
FD_DATABASE_BACKGROUND_PASSWORD=
|
|
93
93
|
|
|
94
|
+
# Model key for a self-hosted sandbox. The application itself never reads it:
|
|
95
|
+
# agents.core keeps every provider credential sealed in the workspace vault,
|
|
96
|
+
# configured in Administration, AI providers. The sandbox reads this name,
|
|
97
|
+
# OPENAI_API_KEY, AZURE_API_KEY and AI_GATEWAY_API_KEY from the environment or
|
|
98
|
+
# from the workspace .env, and an exported variable wins over the file.
|
|
99
|
+
ANTHROPIC_API_KEY=
|
|
100
|
+
|
|
94
101
|
# Prometheus exposition on GET /api/metrics. Leave FD_METRICS unset to keep it off.
|
|
95
102
|
FD_METRICS=false
|
|
96
103
|
FD_METRICS_TOKEN=
|