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.
Files changed (130) hide show
  1. package/README.md +16 -10
  2. package/agent-template/.agents/skills/agent-tool-design/SKILL.md +1 -1
  3. package/agent-template/.agents/skills/auth-security-review/SKILL.md +2 -2
  4. package/agent-template/.agents/skills/bug-hunt/SKILL.md +1 -1
  5. package/agent-template/.agents/skills/database-adapter/SKILL.md +5 -5
  6. package/agent-template/.agents/skills/database-adapter/references/first-run-and-matrix.md +2 -2
  7. package/agent-template/.agents/skills/deploy-operate/SKILL.md +1 -1
  8. package/agent-template/.agents/skills/migration-authoring/SKILL.md +4 -4
  9. package/agent-template/.agents/skills/module-new/SKILL.md +1 -1
  10. package/agent-template/.agents/skills/spec-interview/SKILL.md +20 -20
  11. package/agent-template/.agents/skills/test-hardening/SKILL.md +2 -2
  12. package/agent-template/.agents/skills/ux-design/SKILL.md +1 -1
  13. package/agent-template/.agents/skills/workflow-development/SKILL.md +95 -9
  14. package/agent-template/.ai/README.md +5 -3
  15. package/agent-template/.ai/agents/README.md +1 -1
  16. package/agent-template/.ai/agents/sandbox/agentic-engineer.md +1 -0
  17. package/agent-template/.ai/agents/sandbox/backend-engineer.md +1 -0
  18. package/agent-template/.ai/agents/sandbox/frontend-engineer.md +1 -0
  19. package/agent-template/.ai/blueprints/add-migration/README.md +1 -1
  20. package/agent-template/.ai/blueprints/add-migration/required-files.yaml +1 -1
  21. package/agent-template/.ai/blueprints/new-module/required-files.yaml +1 -1
  22. package/agent-template/.ai/examples/bad/client-imports-server/README.md +1 -1
  23. package/agent-template/.ai/examples/bad/missing-acl/README.md +1 -1
  24. package/agent-template/.ai/examples/bad/tenant-from-body/README.md +1 -1
  25. package/agent-template/.ai/guides/application-development.md +7 -5
  26. package/agent-template/.ai/platform-capabilities.md +9 -5
  27. package/agent-template/.ai/policies/capabilities.yaml +28 -12
  28. package/agent-template/.ai/policies/task-budgets.yaml +1 -1
  29. package/agent-template/.ai/rules/flowdular.md +3 -2
  30. package/agent-template/.ai/skills/README.md +1 -1
  31. package/agent-template/.ai/skills/agent-tool-design/SKILL.md +1 -1
  32. package/agent-template/.ai/skills/auth-security-review/SKILL.md +2 -2
  33. package/agent-template/.ai/skills/bug-hunt/SKILL.md +1 -1
  34. package/agent-template/.ai/skills/database-adapter/SKILL.md +5 -5
  35. package/agent-template/.ai/skills/database-adapter/references/first-run-and-matrix.md +2 -2
  36. package/agent-template/.ai/skills/deploy-operate/SKILL.md +1 -1
  37. package/agent-template/.ai/skills/migration-authoring/SKILL.md +4 -4
  38. package/agent-template/.ai/skills/module-new/SKILL.md +1 -1
  39. package/agent-template/.ai/skills/spec-interview/SKILL.md +20 -20
  40. package/agent-template/.ai/skills/test-hardening/SKILL.md +2 -2
  41. package/agent-template/.ai/skills/ux-design/SKILL.md +1 -1
  42. package/agent-template/.ai/skills/workflow-development/SKILL.md +96 -10
  43. package/agent-template/.ai/subagents/module-executor.md +25 -0
  44. package/agent-template/.ai/subagents/reviewer.md +23 -0
  45. package/agent-template/.ai/subagents/spec-author.md +23 -0
  46. package/agent-template/.claude/agents/module-executor.md +22 -0
  47. package/agent-template/.claude/agents/reviewer.md +24 -0
  48. package/agent-template/.claude/agents/spec-author.md +20 -0
  49. package/agent-template/.claude/skills/agent-tool-design/SKILL.md +1 -1
  50. package/agent-template/.claude/skills/auth-security-review/SKILL.md +2 -2
  51. package/agent-template/.claude/skills/bug-hunt/SKILL.md +1 -1
  52. package/agent-template/.claude/skills/database-adapter/SKILL.md +5 -5
  53. package/agent-template/.claude/skills/database-adapter/references/first-run-and-matrix.md +2 -2
  54. package/agent-template/.claude/skills/deploy-operate/SKILL.md +1 -1
  55. package/agent-template/.claude/skills/migration-authoring/SKILL.md +4 -4
  56. package/agent-template/.claude/skills/module-new/SKILL.md +1 -1
  57. package/agent-template/.claude/skills/spec-interview/SKILL.md +20 -20
  58. package/agent-template/.claude/skills/test-hardening/SKILL.md +2 -2
  59. package/agent-template/.claude/skills/ux-design/SKILL.md +1 -1
  60. package/agent-template/.claude/skills/workflow-development/SKILL.md +95 -9
  61. package/agent-template/.codex/agents/module-executor.toml +17 -0
  62. package/agent-template/.codex/agents/reviewer.toml +14 -0
  63. package/agent-template/.codex/agents/spec-author.toml +15 -0
  64. package/agent-template/AGENTS.md +3 -2
  65. package/agent-template/CLAUDE.md +3 -2
  66. package/agent-template/docs/adr/0007-module-owned-agents.md +35 -1
  67. package/agent-template/docs/agent-contract.md +2 -2
  68. package/agent-template/docs/cli.md +24 -3
  69. package/agent-template/docs/configuration.md +59 -5
  70. package/agent-template/docs/database-adapters.md +20 -20
  71. package/agent-template/docs/design-system.md +3 -3
  72. package/agent-template/docs/getting-started.md +25 -32
  73. package/agent-template/docs/module-distribution.md +79 -86
  74. package/agent-template/docs/module-web-surfaces.md +9 -7
  75. package/agent-template/docs/modules.md +9 -1
  76. package/agent-template/docs/sandbox.md +117 -6
  77. package/agent-template/platform/scripts/build.mjs +7 -0
  78. package/agent-template/rulesync.jsonc +1 -1
  79. package/dist/bin.js +12 -6
  80. package/package.json +2 -2
  81. package/template/default/.env.example +10 -3
  82. package/template/default/.prettierignore +2 -0
  83. package/template/default/.vercelignore +8 -0
  84. package/template/default/README.md +26 -15
  85. package/template/default/_gitignore +3 -2
  86. package/template/default/infra/README.md +86 -65
  87. package/template/default/infra/docker/.env.example +66 -0
  88. package/template/default/infra/docker/Dockerfile +24 -10
  89. package/template/default/infra/docker/app-entrypoint.mjs +5 -0
  90. package/template/default/infra/docker/compose.yaml +105 -58
  91. package/template/default/infra/docker/database-urls.mjs +28 -0
  92. package/template/default/infra/docker/pitr.sh +177 -0
  93. package/template/default/infra/docker/postgres/10-roles.sh +16 -12
  94. package/template/default/infra/docker/start.mjs +402 -0
  95. package/template/default/infra/kubernetes/database-secret.example.yaml +3 -3
  96. package/template/default/infra/vercel/README.md +262 -0
  97. package/template/default/infra/vercel/build.mjs +214 -0
  98. package/template/default/infra/vercel/handler.mjs +100 -0
  99. package/template/default/modules/example/migrations/0001_example_core.up.sql +2 -2
  100. package/template/default/modules/example/module.json +1 -1
  101. package/template/default/modules/example/package.json +3 -3
  102. package/template/default/modules/example/spec/module.yaml +1 -1
  103. package/template/default/modules/example/src/services/migration.ts +2 -2
  104. package/template/default/modules/example/tests/module.test.ts +1 -1
  105. package/template/default/package.json +3 -2
  106. package/template/default/platform/index.html +7 -19
  107. package/template/default/platform/octane.config.ts +252 -156
  108. package/template/default/platform/package.json +5 -5
  109. package/template/default/platform/public/favicon.svg +1 -1
  110. package/template/default/platform/scripts/build.mjs +56 -0
  111. package/template/default/platform/scripts/dev.mjs +38 -0
  112. package/template/default/platform/src/App.tsrx +25 -1
  113. package/template/default/platform/src/generated/modules.server.ts +3 -0
  114. package/template/default/platform/src/server/database.ts +24 -0
  115. package/template/default/platform/src/server/runtime-role.ts +33 -0
  116. package/template/default/platform/src/server/setup/access.ts +160 -0
  117. package/template/default/platform/src/server/setup/adapters.ts +554 -0
  118. package/template/default/platform/src/server/setup/environment.ts +154 -0
  119. package/template/default/platform/src/server/setup/gate.ts +84 -0
  120. package/template/default/platform/src/server/setup/index.ts +181 -0
  121. package/template/default/platform/src/server/setup/modules.ts +123 -0
  122. package/template/default/platform/src/server/setup/page.ts +497 -0
  123. package/template/default/platform/src/server/setup/routes.ts +787 -0
  124. package/template/default/platform/src/server/setup/sanitize.ts +111 -0
  125. package/template/default/platform/src/server/setup/seed.ts +145 -0
  126. package/template/default/platform/src/server/setup/token.ts +79 -0
  127. package/template/default/platform/src/server/worker-tick.ts +193 -0
  128. package/template/default/platform/src/server/workspace-root.ts +16 -0
  129. package/template/default/render.yaml +70 -0
  130. package/template/default/vercel.json +5 -0
@@ -1,6 +1,6 @@
1
1
  # Getting started
2
2
 
3
- Run Flowdular on your machine, seed a demo workspace, and sign in.
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
- ## Seed a local demo
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 flowdular setup quick # dry run, prints the plan
31
- pnpm flowdular setup quick --apply --confirm reset-local-auth # resets and seeds
25
+ pnpm dev
32
26
  ```
33
27
 
34
- Stop `pnpm dev` before applying it. Quick setup is blocked outside development
35
- and test, and must never point at a deployed database.
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
- It creates two demo tenants (Operations Demo, Finance Demo) and two logins:
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
- | Account | Password | Role |
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
- ## Run the platform
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 dev
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
- Open `http://localhost:4310`. Vite HMR covers TSRX, TypeScript and styles. The
51
- launcher keeps tool warnings quiet; use `pnpm dev -- --verbose` for full
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
- # Installing official modules
1
+ # Module Studio
2
2
 
3
- Core is maintained in [Flowdular/flowdular](https://github.com/Flowdular/flowdular).
4
- [Flowdular/official-modules](https://github.com/Flowdular/official-modules) owns
5
- expenses, parties and catalog, including their source, reviews and immutable
6
- release artifacts. The landing is in [Flowdular/landing](https://github.com/Flowdular/landing).
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 search expenses
10
- pnpm flowdular module info expenses.core
11
- pnpm flowdular module install expenses.core@0.8.1
12
- pnpm flowdular module install expenses.core@0.8.1 --apply
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 flowdular module validate --locked
22
+ pnpm build
15
23
  ```
16
24
 
17
- Without `--apply`, installation and updates return a plan and write nothing.
18
- Installation downloads source into the first configured module root and writes
19
- `flowdular.modules.lock.json`. It does not install npm dependencies, run downloaded
20
- scripts, activate modules, grant scopes or touch a database. Enablement links npm
21
- packages with install lifecycle scripts disabled, generates composition and runs
22
- its existing scope-grant flow. Review the source before enabling it.
23
-
24
- `module update <id[@version]> [--apply]` requires an installer-managed module and
25
- refuses local source changes, removed or edited historical migrations, incompatible
26
- versions and downgrades. Additional source files count as local edits. Generated
27
- `dist`, `node_modules` and Git metadata do not. `module validate --locked` requires
28
- a lock and checks source hashes as well as ordinary manifest/dependency validation.
29
-
30
- The installer resolves a consistent dependency closure, including diamond
31
- constraints, within a bounded search budget. Existing workspace/package versions
32
- are preserved. Registry and runtime validation share semver semantics, including
33
- pre-1.0 caret ranges. Every module declares `platformApi` as a range
34
- (`^0.1.0`); the current platform API is `PLATFORM_API_VERSION` in `packages/contracts/src/index.ts` and `module search --compatible`
35
- filters releases by it. A release that declares `requires` is resolved together
36
- with the newest compatible release providing each required capability.
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
- The default catalog is the official repository's `registry/index.json`. HTTPS
41
- artifact URLs must point to the declared immutable commit in that same repository.
42
- Downloads have time and size limits. Source bundles are bounded JSON records of
43
- regular files, validated for path escapes, duplicate names, digest mismatches,
44
- identity, portable dependencies and stale/missing review evidence. No archive
45
- extraction or install lifecycle scripts execute during source installation.
46
-
47
- A checksum does not authenticate an arbitrary publisher. The trust root is the
48
- configured official repository over HTTPS. An operator can explicitly supply
49
- `--registry /absolute/path/index.json` for an offline catalog; artifacts must stay
50
- inside that catalog directory. Third-party remote registries are not supported.
51
- A review report is an assessment, not a guarantee or a defense against a malicious
52
- publisher. Official release CI also executes the checks independently.
53
-
54
- Concurrent installs share an exclusive transaction directory. Recover an
55
- interrupted operation with `module recover` and `module recover --apply` after
56
- its owner process has exited. Recovery restores the previous source and module
57
- lock and refuses to discard conflicting edits. Keep the transaction directory
58
- when a conflict is reported. Source recovery never rolls back database migrations.
59
- Installation and updates are host/operator capabilities and do not expand sandbox
60
- agents' network, filesystem or tool permissions.
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 exactly `@flowdular/sdk`, `flowdular`, `create-flowdular` and `@flowdular/sandbox`, with versions, tarballs
72
- and SHA-256 digests. Publish those tarballs with `npm publish <tarball> --access public`.
73
- Publish all SDK dependencies before consumers install the starter. The three
74
- business modules and the landing are not in this npm publication set. Keep release
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). Choose `/backoffice` to leave `/` available
144
- for a storefront. Setup validates the address, includes it in the review, and
145
- writes `FD_APPLICATION_PATH=/backoffice` alongside the database settings. Restart
146
- after setup; no client rebuild is needed for this environment setting. On a
147
- read-only deployment setup provides the environment block to paste into the
148
- hosting service. If `FD_APPLICATION_PATH` already exists in the environment, it
149
- is authoritative; setup cannot silently replace it.
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.1.0`). The contract surface is pinned in
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
- The launcher walks up to `flowdular.json` to find the workspace and opens
19
- `http://127.0.0.1:4320`. `--port`, `--workspace`, `--host` and `--mode` override
20
- the defaults.
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 is encrypted at rest under `.flowdular/sandbox/secret.key` and is never
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. */
@@ -3,7 +3,7 @@
3
3
  "inputRoots": [".ai"],
4
4
  "outputRoots": ["."],
5
5
  "targets": ["codexcli", "claudecode"],
6
- "features": ["rules", "skills"],
6
+ "features": ["rules", "skills", "subagents"],
7
7
  "delete": true,
8
8
  "verbose": false,
9
9
  "silent": false,
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
- "Choose local demo or PostgreSQL",
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("Local URL", "dim")} ${paint(DEV_URL, "cyan")}`,
326
- ` ${paint("Demo login", "dim")} admin@example.com`,
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.4.3",
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/flowdular/flowdular.git",
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://coreloom_runtime:REPLACE_ME@postgres:5432/flowdular
17
- FD_DATABASE_MIGRATOR_URL=postgresql://coreloom_migrator:REPLACE_ME@postgres:5432/flowdular
18
- FD_DATABASE_BACKGROUND_URL=postgresql://coreloom_background:REPLACE_ME@postgres:5432/flowdular
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=
@@ -6,4 +6,6 @@ AGENTS.md
6
6
  CLAUDE.md
7
7
  .agents/skills/
8
8
  .claude/skills/
9
+ .claude/agents/
10
+ .codex/agents/
9
11
  .ai/references/
@@ -0,0 +1,8 @@
1
+ # vercel deploy uploads whatever its built-in list and this file leave in.
2
+ # The built-in list keeps neither .env files nor local state out, and
3
+ # .flowdular/deploy holds the production keys.
4
+ .env
5
+ .env.*
6
+ !.env.example
7
+ .flowdular
8
+ .octane-erp