anhedral 0.8.6 → 0.9.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 (125) hide show
  1. package/README.md +141 -38
  2. package/assets/anhedral-cli-init-technical.svg +15 -15
  3. package/assets/anhedral-cli-init.svg +16 -16
  4. package/dist/access.d.ts +10 -0
  5. package/dist/access.js +93 -0
  6. package/dist/auth-schema-snapshot.d.ts +346 -0
  7. package/dist/auth-schema-snapshot.js +347 -0
  8. package/dist/auth-schema.d.ts +1 -0
  9. package/dist/auth-schema.js +57 -0
  10. package/dist/bin.js +345 -39
  11. package/dist/bounded-file.d.ts +2 -0
  12. package/dist/bounded-file.js +30 -0
  13. package/dist/capabilities.d.ts +24 -42
  14. package/dist/capabilities.js +73 -75
  15. package/dist/cloudflare.d.ts +14 -0
  16. package/dist/cloudflare.js +66 -0
  17. package/dist/command.js +12 -3
  18. package/dist/delivery.d.ts +118 -0
  19. package/dist/delivery.js +611 -0
  20. package/dist/dependencies.d.ts +24 -3
  21. package/dist/dependencies.js +112 -74
  22. package/dist/dependency-order.d.ts +2 -0
  23. package/dist/dependency-order.js +24 -0
  24. package/dist/index.d.ts +18 -3
  25. package/dist/index.js +12 -2
  26. package/dist/managed-hosting.d.ts +49 -0
  27. package/dist/managed-hosting.js +373 -0
  28. package/dist/management.d.ts +3 -0
  29. package/dist/management.js +47 -0
  30. package/dist/platforms/desktop.d.ts +2 -2
  31. package/dist/platforms/desktop.js +25 -15
  32. package/dist/platforms/extension.d.ts +2 -2
  33. package/dist/platforms/extension.js +104 -66
  34. package/dist/platforms/mobile.d.ts +2 -2
  35. package/dist/platforms/mobile.js +13 -7
  36. package/dist/pnpm-policy.d.ts +0 -2
  37. package/dist/pnpm-policy.js +18 -13
  38. package/dist/project-state.d.ts +28 -0
  39. package/dist/project-state.js +226 -0
  40. package/dist/provider-readiness.d.ts +30 -0
  41. package/dist/provider-readiness.js +87 -0
  42. package/dist/provision.d.ts +46 -0
  43. package/dist/provision.js +197 -0
  44. package/dist/readiness.d.ts +4 -2
  45. package/dist/readiness.js +81 -14
  46. package/dist/registry/add.d.ts +22 -0
  47. package/dist/registry/add.js +198 -0
  48. package/dist/registry/bootstrap.d.ts +2 -0
  49. package/dist/registry/bootstrap.js +14 -0
  50. package/dist/registry/commands.d.ts +2 -0
  51. package/dist/registry/commands.js +99 -0
  52. package/dist/registry/context.d.ts +3 -0
  53. package/dist/registry/context.js +21 -0
  54. package/dist/registry/options.d.ts +2 -0
  55. package/dist/registry/options.js +65 -0
  56. package/dist/registry/receipt.d.ts +3 -0
  57. package/dist/registry/receipt.js +73 -0
  58. package/dist/registry/remote.d.ts +25 -0
  59. package/dist/registry/remote.js +168 -0
  60. package/dist/registry/resolve.d.ts +10 -0
  61. package/dist/registry/resolve.js +98 -0
  62. package/dist/registry/types.d.ts +64 -0
  63. package/dist/registry/usage.d.ts +1 -0
  64. package/dist/registry/usage.js +38 -0
  65. package/dist/render.d.ts +0 -4
  66. package/dist/render.js +3 -16
  67. package/dist/repository.d.ts +24 -0
  68. package/dist/repository.js +96 -0
  69. package/dist/scaffold/api.d.ts +2 -0
  70. package/dist/scaffold/api.js +13 -0
  71. package/dist/scaffold/auth.d.ts +3 -0
  72. package/dist/scaffold/auth.js +95 -0
  73. package/dist/scaffold/bootstrap.d.ts +2 -0
  74. package/dist/scaffold/bootstrap.js +34 -0
  75. package/dist/scaffold/compose.d.ts +4 -0
  76. package/dist/scaffold/compose.js +34 -0
  77. package/dist/scaffold/database.d.ts +2 -0
  78. package/dist/scaffold/database.js +43 -0
  79. package/dist/scaffold/documentation.d.ts +3 -0
  80. package/dist/scaffold/documentation.js +91 -0
  81. package/dist/scaffold/environment.d.ts +2 -0
  82. package/dist/scaffold/environment.js +5 -0
  83. package/dist/scaffold/files.d.ts +25 -0
  84. package/dist/scaffold/files.js +108 -0
  85. package/dist/scaffold/integrations.d.ts +3 -0
  86. package/dist/scaffold/integrations.js +7 -0
  87. package/dist/scaffold/services.d.ts +5 -0
  88. package/dist/scaffold/services.js +84 -0
  89. package/dist/scaffold/web.d.ts +2 -0
  90. package/dist/scaffold/web.js +102 -0
  91. package/dist/scaffold/workspace.d.ts +3 -0
  92. package/dist/scaffold/workspace.js +150 -0
  93. package/dist/security-backports.js +7 -2
  94. package/dist/stack-registry.d.ts +80 -0
  95. package/dist/stack-registry.js +424 -0
  96. package/dist/standard.d.ts +6 -19
  97. package/dist/standard.js +46 -653
  98. package/dist/transaction.js +47 -56
  99. package/dist/util.js +12 -2
  100. package/dist/vercel.d.ts +98 -0
  101. package/dist/vercel.js +796 -0
  102. package/dist/version.d.ts +1 -1
  103. package/dist/version.js +1 -1
  104. package/dist/vinext.d.ts +1 -0
  105. package/dist/vinext.js +83 -0
  106. package/dist/workspace-graph.d.ts +7 -0
  107. package/dist/workspace-graph.js +73 -0
  108. package/docs/application-stack-standard.md +76 -91
  109. package/docs/delivery-workflow.md +83 -0
  110. package/docs/managed-hosting-architecture.md +87 -0
  111. package/docs/sponsorships.md +25 -0
  112. package/package.json +23 -29
  113. package/dist/evidence-validation.d.ts +0 -2
  114. package/dist/evidence-validation.js +0 -18
  115. package/dist/foundation.d.ts +0 -6
  116. package/dist/foundation.js +0 -49
  117. package/dist/progress-view.d.ts +0 -57
  118. package/dist/progress-view.js +0 -69
  119. package/dist/progress.d.ts +0 -95
  120. package/dist/progress.js +0 -327
  121. package/dist/project.d.ts +0 -5
  122. package/dist/standard-products.d.ts +0 -2
  123. package/dist/standard-products.js +0 -6
  124. /package/assets/{images/svg/logo-white-subtract.svg → anhedral-mark.svg} +0 -0
  125. /package/dist/{project.js → registry/types.js} +0 -0
@@ -0,0 +1,87 @@
1
+ # Anhedral Cloud: setup and deployment contract
2
+
3
+ The CLI has `cloud register|stage|save|deploy|status` and a locally tested API client. There is no operated hosting backend, platform login, issued app hostname or managed provisioning service. Everything marked **planned** below is a design requirement, not an available command. Customer-account delivery remains independent; never silently substitute it for requested managed hosting.
4
+
5
+ ## Product boundaries
6
+
7
+ Anhedral is the B2B managed software services business. Anhedral Cloud is its hosting/operations service and client workspace. Anhedral Init (`anhedral` on npm) is the open-source application foundation and CLI; customer-account deployments must work without an Anhedral subscription. Managed delivery is an optional provider adapter, not a dependency hidden in generated application code.
8
+
9
+ Keep `anhedral-landing` as the public website and existing portal frontend initially; retain working Next.js/Vercel hosting while the Hono/Workers control plane is built. Both portal and CLI should consume that same API. One durable model should connect organizations, memberships/roles, engagements, applications, environments, resources, releases and usage. A services project can contain multiple applications; product users are distinct from portal members. The current portal's email-primary membership permits one team per person; expand membership deliberately before multi-organization operator/client access. Private file links need storage-side authorization, not just a private portal page.
10
+
11
+ Use the portal for client progress, approvals, application access, operating status, invoices and exports; expose technical controls according to role. Keep hosted customer code on a separate origin/domain from staff/client sessions. Sell engineering and managed operations with explicit responsibilities and bounded infrastructure usage. Source/data export, recovery and the customer-account deployment path should remain usable when managed hosting ends.
12
+
13
+ Sequence: align released CLI/docs; connect portal organizations to the control-plane registry; ship one independently recoverable private application; prove updates, isolation, backups and cost controls; then add operational/billing UI and selected distribution features. Begin as a managed service for invited clients; expand self-service only after those paths are repeatable.
14
+
15
+ ## Accounts and paid activation
16
+
17
+ Managed users should need Anhedral sign-in only for ordinary hosted apps. Anhedral operates the infrastructure and bills its customers; customer-account hosting keeps providers and bills in the customer's account. Product login remains separate from platform/hosting access.
18
+
19
+ | Owner | Account/service | When and gate |
20
+ | --- | --- | --- |
21
+ | Anhedral | [Cloudflare Workers for Platforms](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/pricing/), DNS zone and scoped deployment credentials | Required managed runtime. Published baseline is $25/month plus overages; purchase currently uses the dashboard. Verify account, subscription and permissions before provisioning. |
22
+ | Anhedral | [Neon serverless driver](https://neon.com/docs/serverless/serverless-driver); optional [Hyperdrive](https://developers.cloudflare.com/hyperdrive/platform/pricing/) | Default direct HTTP Postgres; provision isolated app credentials/data boundaries. Add Hyperdrive only for measured needs, using the non-pooled Neon endpoint. D1 is the SQLite option. Free quotas are not production capacity guarantees. Hyperdrive is included in Workers plans; Neon has separate billing. |
23
+ | Anhedral | [R2](https://developers.cloudflare.com/r2/pricing/), selected Cloudflare services | Source/build archives and app files; compute/storage/operations/AI/media have separate meters. Enable only selected services. |
24
+ | Anhedral | Better Auth, verified sender and optional OAuth provider registrations | Platform identity, recovery and login mail. No customer Clerk account required; selected app identity providers can differ. |
25
+ | Anhedral | Stripe merchant account | Anhedral subscriptions and usage billing. Customer app payments require the app owner's merchant account or deliberate Stripe Connect onboarding; never mix ledgers. |
26
+ | App owner, when selected | RevenueCat, Apple/Google store products; external AI, mail or other providers | Own commercial identity and app integrations. Verification, terms, billing and OAuth consent may require a human; the CLI reports the exact remaining step. |
27
+ | App owner, when distributed | [Apple](https://developer.apple.com/help/account/basics/about-your-developer-account), [Play](https://support.google.com/googleplay/android-developer/answer/6112435), [Chrome](https://developer.chrome.com/docs/webstore/register) publisher accounts | Paid enrollment/registration and identity checks. Native signing/builds and review remain platform-specific; cloud backend deployment does not publish clients. |
28
+ | Optional | GitHub; custom domain/registrar | GitHub export/connection, not a prerequisite for managed source recovery. Platform subdomains use Anhedral DNS; [customer domains](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/plans/) require ownership validation and hostname limits. |
29
+
30
+ Prices/eligibility must be rechecked at activation. Current numeric baseline is a dated October 8, 2026 check, not an app quote. Paid activation requires authorized spending; an agent can prepare setup and resume after enrollment without recreating resources.
31
+
32
+ ## Platform architecture
33
+
34
+ Use separate control-plane and dispatch Workers. Better Auth identifies platform users; Neon holds owners, apps, permissions, resource identities, versions, deployments and billing ledgers. R2 stores immutable source/build archives. Queues/Workflows execute resumable build/provision/deploy jobs. The dispatch Worker maps an authorized hostname to an isolated user Worker; it must not trust a caller-selected worker name.
35
+
36
+ [Workers for Platforms bindings](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/bindings/) support app resources including D1/R2/KV, Durable Objects, Queues, Workflows and Hyperdrive. Attach only that app's resources; use separate credentials and migration/runtime roles for Postgres. Never give user code platform deployment, billing or shared-admin credentials. Build untrusted code in an isolated runner; export only reviewed executable artifacts. Resolve resources on the server from a declared capability manifest, not arbitrary account IDs from uploaded code.
37
+
38
+ Private previews and production enforce platform audience at dispatch, including assets, APIs and WebSocket upgrades. In-app authorization is still the application's responsibility. Test the chosen framework in the actual dispatch runtime: [platform limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/limits/) include disabled `caches.default` and restricted `request.cf` in untrusted namespaces. Do not enable trusted mode for customer code to bypass compatibility failures. User Workers currently lack gradual deployments; use immutable versioned Worker names plus an authorized routing switch for previews/rollback, and verify WebSocket/stateful-version compatibility.
39
+
40
+ ## Agent workflow
41
+
42
+ **Planned interface:** `cloud login` → `cloud plan --json` → implement/check/commit → `cloud ship --json --wait` → `cloud verify`. Login should use a browser/device authorization flow and OS-protected renewable credentials. CI uses revocable project-scoped credentials. JSON output should distinguish setup required, payment required, queued, failed, deployed and verified, with resumable operation IDs and non-secret next actions.
43
+
44
+ `plan` must identify owner/environment, declared resources, provider access, compatibility, estimated cost and authorized limits without mutations. `ship` should check source/build provenance, resolve resources, stage/save, apply reviewed compatible migrations, deploy, poll to completion and return the independently confirmed URL. Neither command exists yet. `new --hosting anhedral` is also not supported; generation currently selects Cloudflare or Vercel.
45
+
46
+ The current low-level sequence is executable only with an operated compatible backend and configured `ANHEDRAL_HOSTING_ORIGIN` / `ANHEDRAL_HOSTING_TOKEN`:
47
+
48
+ ```sh
49
+ anhedral cloud register my-app --audience private --json
50
+ # Review source/secrets and commit the managed manifest in the app's own Git repo.
51
+ git -C my-app add <reviewed-paths>
52
+ git -C my-app commit -m "Prepare application version"
53
+ pnpm --dir my-app run check
54
+ # Build a complete self-contained Worker bundle/assets into an ignored app directory.
55
+ anhedral cloud stage my-app --artifact /absolute/path/my-app/build --json
56
+ anhedral cloud save my-app --version <returned-stage-id> --json
57
+ anhedral cloud deploy my-app --version <returned-stage-id> --json
58
+ anhedral cloud status my-app --json
59
+ ```
60
+
61
+ Current `deploy` requests deployment and checks once; it may return queued/building. It does not wait for completion, run product acceptance or implement managed rollback/export. `save` writes connected identity into the tracked manifest; review/commit that change before staging a subsequent version. A staged artifact is not proven to originate from its source merely because both were archived: the planned build receipt must bind source commit, lockfile, toolchain and artifact digest.
62
+
63
+ ## Source and API contract
64
+
65
+ Local Git remains the working source of truth. Save the exact clean commit plus complete build tree; retain immutable version IDs, SHA-256 hashes and byte lengths. Current staging permits regular files only, at most 64 MiB per archive and 10,000 build files; it rejects symlinks/submodules and credential files. Restore/clone/export must preserve history and allow exit; optional [Artifacts](https://developers.cloudflare.com/artifacts/platform/pricing/) can add Git-compatible managed history but is Paid-plan-only and has separately published metering.
66
+
67
+ Current API routes are under `/v1`. Authenticate every route, derive ownership from the session, preserve audience and validate project/version identity. Pin service origin and owner after connection; forbid redirects and credential-bearing origins.
68
+
69
+ | Route | Contract |
70
+ | --- | --- |
71
+ | `GET /session` | Authenticated owner identity. |
72
+ | `POST /projects`, `GET /projects/:id` | Idempotent registration/current owned project state. |
73
+ | `POST /projects/:id/versions` | Immutable commit, hashes/lengths and version identity. |
74
+ | `PUT /projects/:id/versions/:version/source` or `/artifact` | Independently verify uploaded hashes/lengths. |
75
+ | `GET /projects/:id/versions/:version` | Saved only when both verified archives exist. |
76
+ | `POST /projects/:id/deployments` | Idempotent deployment of exact saved version/audience. |
77
+ | `GET /projects/:id/deployments/:deployment` | Independently confirmed state/source/artifact; HTTPS URL only when deployed. |
78
+
79
+ Validate archives again server-side before extraction, including traversal, links, duplicate paths and decompression/size limits. Preserve incomplete upload/job evidence for safe retries. Saving source, deploying code and passing product tests remain separate states.
80
+
81
+ ## Limits and completion gates
82
+
83
+ Enforce [dispatch CPU/subrequest limits](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/configuration/custom-limits/) plus application-owned request, storage, SQL, job, AI/media and outbound budgets. Provider alerts are not hard spend caps. Reserve costly work transactionally before execution; reconcile completion/failure idempotently. Rate-limit platform API jobs with bounded retry/backoff for provider throttling. Limit previews/builds, concurrent jobs and retention; define grace/suspension/export policies. Do not delete customer data merely because billing fails. Optional paid/beta/enterprise services need explicit eligibility checks and adapters; free analytics does not make the rest free.
84
+
85
+ Build in this order: platform identity and account/subscription preflight; durable registry/archive API; isolated build/resource provisioning; dispatch/private routes; resumable deployment polling; logs/secrets/recovery/export; billing/quotas; signed client distribution where requested. First acceptance fixture: two owners, independent private apps, persistence, file upload, one bounded job and repeated update. Prove cross-tenant rejection, anonymous denial, interrupted-save/deploy retry, source restoration, quota rejection and code rollback/data compatibility before onboarding.
86
+
87
+ Maintain this single contract as capabilities ship: replace planned claims with verified command/API behavior and update account/limit links. Keep dated test evidence in existing release/test artifacts, not new analysis documents. Deployment and publication remain unproven until the operated service and installed agent workflow pass acceptance.
@@ -0,0 +1,25 @@
1
+ # Support Anhedral Init
2
+
3
+ ## Help more people build applications they own
4
+
5
+ Anhedral Init is free and open source. We build tools that help developers turn an idea into an application with source code, infrastructure, and data in their own accounts.
6
+
7
+ If Anhedral Init helps you build, saves you time, or makes your work easier, consider supporting its continued development. Your support helps us improve the tools, maintain integrations, fix bugs, and write clearer documentation.
8
+
9
+ ## GitHub Sponsors — coming soon
10
+
11
+ Support can be a thank-you for something useful today or an ongoing contribution to the project's future. Every contribution helps us spend more time improving Anhedral Init for the people who use it.
12
+
13
+ We plan to offer donations and ongoing sponsorships through GitHub Sponsors. Our sponsorship profile is not available yet; we'll add the link here when it launches.
14
+
15
+ In the meantime, [contact us at business@anhedral.com](mailto:business@anhedral.com?subject=Support%20Anhedral%20Init) if you'd like to support the project.
16
+
17
+ ## Company sponsorships
18
+
19
+ Does your company use Anhedral Init or want to support its development? We'd love to hear from you. Get in touch to discuss a sponsorship and how we can recognize your support.
20
+
21
+ **[Become a sponsor](mailto:business@anhedral.com?subject=Anhedral%20Init%20sponsorship)**
22
+
23
+ Thank you for helping us keep Anhedral Init free, open source, and improving.
24
+
25
+ [Back to Anhedral Init](../README.md)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "anhedral",
3
- "version": "0.8.6",
4
- "description": "Initialize client-owned applications from curated platform recipes and selected services.",
3
+ "version": "0.9.0",
4
+ "description": "Build and deliver applications with Cloudflare-first Vinext, selected services, optional Next.js on Vercel, and verified release evidence.",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
@@ -18,12 +18,15 @@
18
18
  "dist",
19
19
  "assets/anhedral-cli-init.svg",
20
20
  "assets/anhedral-cli-init-technical.svg",
21
- "assets/images/svg/logo-white-subtract.svg",
21
+ "assets/anhedral-mark.svg",
22
22
  "LICENSE",
23
23
  "README.md",
24
24
  "assets/anhedral.svg",
25
25
  "assets/favicon.ico",
26
26
  "docs/application-stack-standard.md",
27
+ "docs/delivery-workflow.md",
28
+ "docs/sponsorships.md",
29
+ "docs/managed-hosting-architecture.md",
27
30
  "assets/security"
28
31
  ],
29
32
  "homepage": "https://github.com/anhedral/anhedral-init#readme",
@@ -44,14 +47,14 @@
44
47
  "scripts": {
45
48
  "scaffold": "node dist/bin.js init",
46
49
  "clean": "node scripts/clean.mjs",
47
- "build": "pnpm clean && tsc && node scripts/prepare-cli.mjs && node scripts/build-control-panel.mjs",
50
+ "build": "pnpm clean && tsc && node scripts/prepare-cli.mjs",
48
51
  "prepare": "pnpm build",
49
- "typecheck": "tsc --noEmit && tsc -p apps/control-panel/tsconfig.json",
52
+ "typecheck": "tsc --noEmit",
50
53
  "check:hygiene": "node scripts/check-source-hygiene.mjs",
51
54
  "check:security": "node scripts/check-security-policy.mjs",
52
55
  "check:release-policy": "node scripts/check-release-policy.mjs",
53
56
  "check:release-secrets": "node scripts/check-release-secrets.mjs",
54
- "lint": "pnpm typecheck && pnpm check:hygiene && pnpm check:release-policy",
57
+ "lint": "pnpm typecheck && pnpm format:check && pnpm check:hygiene && pnpm check:release-policy",
55
58
  "audit:osv": "node scripts/audit-osv.mjs",
56
59
  "test": "pnpm test:unit",
57
60
  "pretest": "pnpm build",
@@ -72,7 +75,11 @@
72
75
  "test:standard": "pnpm build && node --test tests/test-standard.test.mjs",
73
76
  "test:unit": "node --test --test-concurrency=4 --test-reporter=spec tests/*.test.mjs",
74
77
  "test:integration": "pnpm build && node tests/test-generated-apps.mjs",
75
- "dev:panel": "node .artifacts/control-panel/preview.js"
78
+ "test:live:delivery": "pnpm build && node tests/test-live-delivery.mjs",
79
+ "test:live:vercel": "pnpm build && node tests/test-live-vercel.mjs",
80
+ "test:live:vercel:git": "pnpm build && node tests/test-live-vercel-git.mjs",
81
+ "format": "prettier --write src scripts tests",
82
+ "format:check": "prettier --check src scripts tests"
76
83
  },
77
84
  "keywords": [
78
85
  "cli",
@@ -88,31 +95,18 @@
88
95
  "neon",
89
96
  "drizzle",
90
97
  "shadcn",
91
- "turborepo"
98
+ "turborepo",
99
+ "vinext"
92
100
  ],
93
101
  "license": "Apache-2.0",
94
- "packageManager": "pnpm@12.9.1",
102
+ "packageManager": "pnpm@10.34.5",
95
103
  "devDependencies": {
96
- "@base-ui/react": "1.8.0",
97
- "@modelcontextprotocol/ext-apps": "1.7.5",
98
- "@modelcontextprotocol/sdk": "1.32.1",
99
- "@openai/mcp-extensions": "0.1.0",
100
- "@tailwindcss/node": "4.3.3",
101
- "@tailwindcss/oxide": "4.3.3",
102
104
  "@types/node": "20.19.43",
103
- "@types/react": "19.3.0",
104
- "@types/react-dom": "19.3.0",
105
- "class-variance-authority": "0.7.1",
106
- "cn": "0.4.0",
107
- "esbuild": "0.28.2",
108
- "jsonc-parser": "3.3.1",
109
- "lucide-react": "1.52.0",
110
- "react": "19.3.0",
111
- "react-dom": "19.3.0",
112
- "simple-icons": "16.34.0",
113
- "tailwindcss": "4.3.3",
114
- "tw-animate-css": "1.4.0",
115
- "typescript": "6.0.3",
116
- "zod": "4.6.5"
105
+ "prettier": "3.9.10",
106
+ "simple-icons": "16.27.0",
107
+ "typescript": "5.9.3"
108
+ },
109
+ "dependencies": {
110
+ "jsonc-parser": "3.3.1"
117
111
  }
118
112
  }
@@ -1,2 +0,0 @@
1
- export declare function isNonSecretEvidence(value: string): boolean;
2
- export declare function isProgressEnvironment(value: string): boolean;
@@ -1,18 +0,0 @@
1
- /** Shared, dependency-free validation for public progress and plugin evidence. */
2
- const forbiddenEvidence = /(?:postgres(?:ql)?:\/\/|bearer\s+\S+|(?:api[_-]?key|secret|password|token)\s*[:=]\s*\S+|\b(?:sk|pk)_(?:live|test|proj)_\S+|\bsk-(?:proj-|live_|test_)?[a-zA-Z0-9_-]{12,}|-----BEGIN [A-Z ]*PRIVATE KEY-----|\bAKIA[A-Z0-9]{16}\b|\b(?:gh[pousr]_|github_pat_)[A-Za-z0-9_]+|\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)/i;
3
- export function isNonSecretEvidence(value) {
4
- if (/[\x00-\x08\x0b-\x1f]/.test(value) || forbiddenEvidence.test(value))
5
- return false;
6
- for (const candidate of value.matchAll(/\b(?:https?|wss?):[^\s<>"']+/gi)) {
7
- try {
8
- const target = new URL(candidate[0]);
9
- if (target.username || target.password)
10
- return false;
11
- }
12
- catch { /* Non-URL prose is validated by the bounded text contract. */ }
13
- }
14
- return true;
15
- }
16
- export function isProgressEnvironment(value) {
17
- return /^[a-zA-Z0-9_-][a-zA-Z0-9._-]{0,79}$/.test(value) && !['__proto__', 'constructor', 'prototype'].includes(value);
18
- }
@@ -1,6 +0,0 @@
1
- export declare const SHADCN_VERSION = "4.21.3";
2
- export declare const SHADCN_BOOTSTRAP: string[];
3
- /** A shared JS workspace is independent of any UI framework bootstrap. */
4
- export declare function scaffoldFoundation(root: string): void;
5
- /** The intentionally small single-app recipe has no shared packages or task runner. */
6
- export declare function flattenSingleApi(root: string, name: string): void;
@@ -1,49 +0,0 @@
1
- import { cpSync, readFileSync, rmSync } from 'node:fs';
2
- import path from 'node:path';
3
- import { writeFile } from './util.js';
4
- import { PACKAGE_MANAGER, TURBO_VERSION } from './dependencies.js';
5
- import { generatedPnpmPolicy, setPnpmPolicy } from './pnpm-policy.js';
6
- // Curated input version; upstream registry templates still require compatibility checks.
7
- export const SHADCN_VERSION = '4.21.3';
8
- export const SHADCN_BOOTSTRAP = ['pnpm', 'dlx', `shadcn@${SHADCN_VERSION}`, 'init', '--monorepo', '--template', 'next'];
9
- const json = (root, file, value) => writeFile(path.join(root, file), JSON.stringify(value, null, 2) + '\n');
10
- /** A shared JS workspace is independent of any UI framework bootstrap. */
11
- export function scaffoldFoundation(root) {
12
- json(root, 'package.json', { name: 'anhedral-workspace', private: true, packageManager: PACKAGE_MANAGER, devDependencies: { turbo: TURBO_VERSION } });
13
- writeFile(path.join(root, 'pnpm-workspace.yaml'), 'packages:\n - "apps/*"\n - "packages/*"\n');
14
- json(root, 'turbo.json', { $schema: 'https://turbo.build/schema.json', tasks: { build: { dependsOn: ['^build'] }, lint: { dependsOn: ['^lint'] }, typecheck: { dependsOn: ['^typecheck'] }, dev: { cache: false, persistent: true } } });
15
- json(root, 'packages/eslint-config/package.json', { name: '@workspace/eslint-config', private: true, type: 'module', exports: { './base': './base.js', './react-internal': './react-internal.js' }, devDependencies: { eslint: '9.39.5', '@eslint/js': '9.39.5', 'typescript-eslint': '8.71.1', 'eslint-plugin-react-hooks': '7.1.1', typescript: '6.0.3' } });
16
- writeFile(path.join(root, 'packages/eslint-config/base.js'), `import js from '@eslint/js';
17
- import ts from 'typescript-eslint';
18
- export const config = [js.configs.recommended, ...ts.configs.recommended, { ignores: ['**/dist/**', '**/.output/**', '**/.wxt/**', '**/.expo/**', '**/node_modules/**'] }];
19
- `);
20
- writeFile(path.join(root, 'packages/eslint-config/react-internal.js'), `import { config as base } from './base.js';
21
- import hooks from 'eslint-plugin-react-hooks';
22
- export const config = [...base, { files: ['**/*.{tsx,jsx}'], plugins: { 'react-hooks': hooks }, rules: { 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn' } }];
23
- `);
24
- json(root, 'packages/typescript-config/package.json', { name: '@workspace/typescript-config', private: true, exports: { './base.json': './base.json' } });
25
- json(root, 'packages/typescript-config/base.json', { compilerOptions: { target: 'ES2022', module: 'ESNext', moduleResolution: 'Bundler', strict: true, skipLibCheck: true, noEmit: true } });
26
- }
27
- /** The intentionally small single-app recipe has no shared packages or task runner. */
28
- export function flattenSingleApi(root, name) {
29
- const read = (file) => JSON.parse(readFileSync(path.join(root, file), 'utf8'));
30
- const workspace = read('package.json');
31
- const app = read('apps/api/package.json');
32
- cpSync(path.join(root, 'apps/api'), root, { recursive: true });
33
- delete app.devDependencies['@workspace/eslint-config'];
34
- const config = read('packages/eslint-config/package.json');
35
- delete config.devDependencies['eslint-plugin-react-hooks'];
36
- // The standalone API has no React/Babel browser-target dependency chain.
37
- const overrides = generatedPnpmPolicy(root, 'overrides');
38
- for (const key of ['baseline-browser-mapping@<2.11.0', 'browserslist@<4.28.7'])
39
- delete overrides[key];
40
- const scripts = { ...workspace.scripts, ...app.scripts, test: 'node --test', 'audit:full': 'fallow --fail-on-issues' };
41
- json(root, 'package.json', { ...app, name, packageManager: PACKAGE_MANAGER, engines: workspace.engines, scripts, devDependencies: { ...config.devDependencies, ...app.devDependencies, eslint: '9.39.5', fallow: workspace.devDependencies.fallow } });
42
- writeFile(path.join(root, 'eslint.config.mjs'), `import js from '@eslint/js';
43
- import ts from 'typescript-eslint';
44
- export default [js.configs.recommended, ...ts.configs.recommended, { ignores: ['dist/**', '.wrangler/**', 'worker-configuration.d.ts'] }, { files: ['**/*.mjs'], languageOptions: { globals: { process: 'readonly' } } }, { files: ['**/*.ts'], rules: { 'no-undef': 'off', 'no-unused-vars': 'off' } }];
45
- `);
46
- for (const file of ['apps', 'packages', 'turbo.json', 'pnpm-workspace.yaml'])
47
- rmSync(path.join(root, file), { recursive: true, force: true });
48
- setPnpmPolicy(root, { allowBuilds: { esbuild: true, workerd: true }, overrides });
49
- }
@@ -1,57 +0,0 @@
1
- import type { evaluateProjectProgress } from "./progress.js";
2
- export type EnvironmentProgress = ReturnType<typeof evaluateProjectProgress>["environments"][number];
3
- interface ProgressNode {
4
- label?: string;
5
- id: string;
6
- capability?: string;
7
- resourceId?: string;
8
- status: "planned" | "building" | "configured" | "verified" | "blocked";
9
- }
10
- export interface ProviderObservation {
11
- id: string;
12
- name: string;
13
- status: string;
14
- }
15
- export declare function componentResources<T extends ProviderObservation>(node: ProgressNode, resources: readonly T[]): T[];
16
- export declare function providerAttention(resources: readonly ProviderObservation[]): boolean;
17
- export declare function componentObservations(progress: EnvironmentProgress | undefined, node: ProgressNode): {
18
- stale: boolean;
19
- capability: string;
20
- milestone: import("./progress.js").Milestone;
21
- configurationFingerprint: string;
22
- resourceRef?: string;
23
- revisionRef?: string;
24
- outcome: "passed" | "failed" | "blocked";
25
- source: "agent" | "independent";
26
- observedAt: string;
27
- evidence: string;
28
- accountRef?: string;
29
- }[];
30
- export declare function latestObservations(observations: EnvironmentProgress["observations"]): {
31
- stale: boolean;
32
- capability: string;
33
- milestone: import("./progress.js").Milestone;
34
- configurationFingerprint: string;
35
- resourceRef?: string;
36
- revisionRef?: string;
37
- outcome: "passed" | "failed" | "blocked";
38
- source: "agent" | "independent";
39
- observedAt: string;
40
- evidence: string;
41
- accountRef?: string;
42
- }[];
43
- export declare function componentState(progress: EnvironmentProgress | undefined, node: ProgressNode, resources?: readonly ProviderObservation[]): "blocked" | "planned" | "building" | "configured" | "verified";
44
- /** A failed optional route does not block a working alternative for the same scope. */
45
- export declare function discoveryAttention(discovery: EnvironmentProgress["discovery"]): {
46
- stale: boolean;
47
- provider: string;
48
- route: "plugin" | "api" | "cli" | "browser";
49
- check: "installed" | "callable" | "local-working" | "authorized" | "integration-tested";
50
- expiresAt: string;
51
- outcome: "passed" | "failed" | "blocked";
52
- source: "agent" | "independent";
53
- observedAt: string;
54
- evidence: string;
55
- accountRef?: string;
56
- }[];
57
- export {};
@@ -1,69 +0,0 @@
1
- export function componentResources(node, resources) {
2
- return resources.filter((resource) => node.resourceId
3
- ? resource.id === node.resourceId
4
- : resource.id === node.id ||
5
- (!!node.label && resource.name === node.label));
6
- }
7
- export function providerAttention(resources) {
8
- return resources.some((resource) => resource.status === "missing" || resource.status === "error");
9
- }
10
- export function componentObservations(progress, node) {
11
- return (progress?.observations.filter((item) => (item.capability === (node.capability || node.id) &&
12
- (!node.resourceId ||
13
- !item.resourceRef ||
14
- item.resourceRef === node.resourceId)) ||
15
- (!!node.resourceId && item.resourceRef === node.resourceId)) || []);
16
- }
17
- export function latestObservations(observations) {
18
- const latest = new Map();
19
- for (const observation of observations) {
20
- const key = JSON.stringify([
21
- observation.capability,
22
- observation.milestone,
23
- observation.source,
24
- observation.accountRef,
25
- observation.resourceRef,
26
- ]);
27
- const previous = latest.get(key);
28
- if (!previous ||
29
- Date.parse(observation.observedAt) >= Date.parse(previous.observedAt))
30
- latest.set(key, observation);
31
- }
32
- return [...latest.values()];
33
- }
34
- export function componentState(progress, node, resources = []) {
35
- if (providerAttention(componentResources(node, resources)))
36
- return "blocked";
37
- const observations = latestObservations(componentObservations(progress, node));
38
- const current = observations.filter((item) => !item.stale);
39
- if (current.some((item) => item.outcome !== "passed"))
40
- return "blocked";
41
- if (current.some((item) => item.milestone === "tested"))
42
- return "verified";
43
- if (current.some((item) => ["provisioned", "connected"].includes(item.milestone)))
44
- return "configured";
45
- if (current.some((item) => item.milestone === "generated"))
46
- return "building";
47
- if (observations.length)
48
- return "planned";
49
- return node.status;
50
- }
51
- /** A failed optional route does not block a working alternative for the same scope. */
52
- export function discoveryAttention(discovery) {
53
- const level = {
54
- installed: 0,
55
- callable: 1,
56
- "local-working": 1,
57
- authorized: 2,
58
- "integration-tested": 3,
59
- };
60
- const current = discovery.filter((item) => !item.stale);
61
- return current.filter((item) => item.outcome !== "passed" &&
62
- !current.some((other) => other.outcome === "passed" &&
63
- other.provider === item.provider &&
64
- other.route !== item.route &&
65
- (!item.accountRef || other.accountRef === item.accountRef) &&
66
- (item.source !== "independent" || other.source === "independent") &&
67
- level[other.check] >= level[item.check] &&
68
- level[other.check] >= 2));
69
- }
@@ -1,95 +0,0 @@
1
- export declare const PROGRESS_FILE = "anhedral.progress.json";
2
- export declare const MILESTONES: readonly ["generated", "provisioned", "connected", "tested", "deployed"];
3
- export type Milestone = typeof MILESTONES[number];
4
- type Outcome = 'passed' | 'failed' | 'blocked';
5
- type Source = 'agent' | 'independent';
6
- interface Evidence {
7
- outcome: Outcome;
8
- source: Source;
9
- observedAt: string;
10
- evidence: string;
11
- accountRef?: string;
12
- }
13
- export interface ProgressObservation extends Evidence {
14
- capability: string;
15
- milestone: Milestone;
16
- configurationFingerprint: string;
17
- resourceRef?: string;
18
- revisionRef?: string;
19
- }
20
- export interface DiscoveryObservation extends Evidence {
21
- provider: string;
22
- route: 'plugin' | 'api' | 'cli' | 'browser';
23
- check: 'installed' | 'callable' | 'local-working' | 'authorized' | 'integration-tested';
24
- expiresAt: string;
25
- }
26
- export interface ProgressEnvironment {
27
- id: string;
28
- observations: ProgressObservation[];
29
- discovery: DiscoveryObservation[];
30
- blockers: string[];
31
- nextAction?: string;
32
- previewUrl?: string;
33
- liveUrl?: string;
34
- }
35
- export interface ProjectProgress {
36
- schemaVersion: 1;
37
- revision: number;
38
- updatedAt: string;
39
- environments: ProgressEnvironment[];
40
- }
41
- export interface ProgressReport {
42
- revision: number;
43
- environment: string;
44
- observations?: ProgressObservation[];
45
- discovery?: DiscoveryObservation[];
46
- blockers?: string[];
47
- nextAction?: string | null;
48
- previewUrl?: string | null;
49
- liveUrl?: string | null;
50
- }
51
- export declare function validateProgressReport(value: unknown): ProgressReport;
52
- export declare function validateProjectProgress(value: unknown): ProjectProgress;
53
- export declare function readProjectProgress(root: string): ProjectProgress | null;
54
- /** Bounded source/configuration digest; secrets, dependencies and generated output are excluded. */
55
- export declare function projectFingerprint(root: string): string;
56
- /** Reports are caller assertions. Only actual checking adapters should use source: independent. */
57
- export declare function reportProjectProgress(root: string, input: ProgressReport): ProjectProgress;
58
- export declare function evaluateProjectProgress(record: ProjectProgress, fingerprint: string, now?: number): {
59
- environments: {
60
- observations: {
61
- stale: boolean;
62
- capability: string;
63
- milestone: Milestone;
64
- configurationFingerprint: string;
65
- resourceRef?: string;
66
- revisionRef?: string;
67
- outcome: Outcome;
68
- source: Source;
69
- observedAt: string;
70
- evidence: string;
71
- accountRef?: string;
72
- }[];
73
- discovery: {
74
- stale: boolean;
75
- provider: string;
76
- route: "plugin" | "api" | "cli" | "browser";
77
- check: "installed" | "callable" | "local-working" | "authorized" | "integration-tested";
78
- expiresAt: string;
79
- outcome: Outcome;
80
- source: Source;
81
- observedAt: string;
82
- evidence: string;
83
- accountRef?: string;
84
- }[];
85
- id: string;
86
- blockers: string[];
87
- nextAction?: string;
88
- previewUrl?: string;
89
- liveUrl?: string;
90
- }[];
91
- schemaVersion: 1;
92
- revision: number;
93
- updatedAt: string;
94
- };
95
- export {};