minutework 0.1.53 → 0.1.55

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 CHANGED
@@ -147,7 +147,7 @@ minutework deploy --preview
147
147
 
148
148
  Combined **tenant-app + sidecar** workspaces keep sidecar setup explicit. Root `pnpm install` stays Node-only and does not run `poetry install` for you. If you need the sidecar, run `pnpm run install:sidecar` from the workspace root or `cd sidecar && poetry install` yourself before `minutework dev` or `minutework test`. Sidecar-only scaffolds have no root `package.json`; install Python deps once inside `sidecar/` before running local sidecar workflows.
149
149
 
150
- For direct third-party web hosts such as Vercel, deploy `tenant-app` only. In Vercel, point the project Root Directory at `tenant-app`; the optional sidecar remains a separate Poetry-managed surface. To keep `@minutework/web-auth` same-origin on a bring-your-own host, set `MW_GATEWAY_BASE_URL` to the platform gateway base URL — the template's `next.config.mjs` then proxies `/_mw/*` to the gateway — and run `minutework deploy --live --host <your-domain>` so the gateway recognizes that host as your tenant's live canonical customer-web origin.
150
+ For direct third-party web hosts such as Vercel, deploy `tenant-app` only. In Vercel, point the project Root Directory at `tenant-app`; the optional sidecar remains a separate Poetry-managed surface. To keep `@minutework/web-auth` same-origin on a bring-your-own host, set `MW_GATEWAY_BASE_URL` to the canonical live customer-web host returned by `minutework deploy --live` — the template's `next.config.mjs` then proxies `/_mw/*` to the gateway — and run `minutework deploy --live --host <your-domain>` so the gateway recognizes that host as your tenant's live canonical customer-web origin. For local auth against dev, target `https://dev.minutework.ai`, deploy live there, then set `MW_GATEWAY_BASE_URL` to the returned `https://<label>.customers.dev.minutework.ai` host, not bare `https://dev.minutework.ai`.
151
151
 
152
152
  `link` provisions or resolves the default published-site property for the active tenant and stores that property key in repo-local state. The SDK-based `tenant-app/.env.example` contains only the app metadata contract used by the template: `NEXT_PUBLIC_MW_APP_ID`, `MW_TEMPLATE_APP_NAME`, and optional `MW_PUBLIC_BASE_URL`. Browser auth and manifest calls use same-origin `/_mw` routes through `@minutework/web-auth`; do not add platform content tokens or public-site property vars to the tenant app.
153
153
 
@@ -21,6 +21,13 @@ published app pack installed, and use it through the branded `vuilder-shell`.
21
21
  The Vuilder owns and resells this product; their customers each run an isolated
22
22
  tenant.
23
23
 
24
+ That signup=auto-spawn path is **Mode A**. Some Vuilders are **Mode B**: they run
25
+ a shared hosted broker/demo on their own operator runtime that customers join via
26
+ `/_mw` and use first, then provision their OWN runtime later as an opt-in step.
27
+ Decide Mode A vs Mode B early — `skills/vuilder-workspace-architecture/SKILL.md`
28
+ leads with that choice and routes Mode B to
29
+ `skills/vuilder-mode-b-hosted-and-spawn/SKILL.md`.
30
+
24
31
  `tenant-app`, `sidecar`, and `mobile` starters are **not** enabled in this
25
32
  workspace unless `minutework.config.ts` says otherwise — do not assume those
26
33
  surfaces exist. The generic builder guidance below still governs how you write
@@ -53,6 +53,7 @@ Generated-workspace-first guidance should live here, especially:
53
53
  - `generated-workspace-architecture/SKILL.md`
54
54
  - `vuilder-workspace-architecture/SKILL.md`
55
55
  - `vuilder-public-site-authoring/SKILL.md`
56
+ - `vuilder-mode-b-hosted-and-spawn/SKILL.md`
56
57
  - `workspace-guidance-refresh/SKILL.md`
57
58
  - `shell-architecture/SKILL.md`
58
59
  - `runtime-capability-inventory/SKILL.md`
@@ -55,6 +55,14 @@ unattended; without `--yes` it returns `confirmation_required`).
55
55
  activate. On a BYO host, set `MW_GATEWAY_BASE_URL` in the tenant-app so the
56
56
  template's `next.config.mjs` proxies same-origin `/_mw/*` to the gateway
57
57
  (managed-subdomain hosts are gateway-fronted and need no rewrite).
58
+ - **Local tenant-app against the dev platform:** target the dev platform
59
+ explicitly (`export MW_CLI_PLATFORM_BASE_URL=https://dev.minutework.ai` and
60
+ `minutework login --platform https://dev.minutework.ai`), link a sandbox
61
+ runtime, then run `minutework deploy --live`. Set `tenant-app/.env.local`
62
+ `MW_GATEWAY_BASE_URL` to the returned canonical live customer-web host such as
63
+ `https://<label>.customers.dev.minutework.ai` before running local `next dev`.
64
+ Do not set it to bare `https://dev.minutework.ai`; the gateway resolves
65
+ `/_mw` customer auth by the live customer-web host.
58
66
 
59
67
  ## Boundaries and current limits
60
68
 
@@ -0,0 +1,184 @@
1
+ ---
2
+ name: vuilder-mode-b-hosted-and-spawn
3
+ description: "Mode B Vuilder: run a hosted broker/demo on your operator runtime, let customers join via /_mw, and offer opt-in 'spawn my own runtime' later (configurable trigger). Use when customers try a hosted product before getting their own server."
4
+ ---
5
+
6
+ # Vuilder Mode B: Hosted Broker/Demo + Opt-In Spawn
7
+
8
+ Use this skill when a generated Vuilder workspace runs a **hosted product** on
9
+ its own operator runtime that customers consume first, and only **later** do
10
+ those customers provision their **own** runtime. Read
11
+ `vuilder-workspace-architecture/SKILL.md` first; this skill specializes it.
12
+
13
+ This skill is vertical-neutral. FleetRun and Ostronaut appear only as clearly
14
+ marked illustrative examples — never as platform behavior to hardcode.
15
+
16
+ ## Mode A vs Mode B — decide which you are
17
+
18
+ - **Mode A (signup = auto-spawn).** A customer signs up on the Vuilder public
19
+ site and the platform immediately provisions a fresh customer tenant runtime
20
+ and installs the app pack. This is the default flow in
21
+ `vuilder-workspace-architecture` (`customer_vertical_signup`). Pick Mode A
22
+ when every customer needs their own isolated runtime from day one.
23
+ - **Mode B (hosted broker/demo, then opt-in spawn).** The Vuilder runs a shared
24
+ hosted product on its **operator runtime**. Customers **join the host
25
+ runtime** via `/_mw` customer auth and use the product there (a broker, a
26
+ demo, a shared workspace). Each customer provisions their **own** runtime
27
+ **later**, as an explicit opt-in step — keeping their identity and history.
28
+ Pick Mode B when customers should try value before committing to their own
29
+ server, or when their own runtime should appear only once a condition holds.
30
+
31
+ > Illustrative only:
32
+ > - *FleetRun* (insurance brokering): carriers sign up as customers of the
33
+ > host runtime and opt to spawn their own runtime when they are ready.
34
+ > - *Ostronaut* (retail conversation intelligence): stores try a hosted demo
35
+ > and spawn their own runtime when real store data starts flowing.
36
+ >
37
+ > Both are instances of the same vertical-neutral shape; do not copy their
38
+ > vocabulary into schemas, manifests, or services.
39
+
40
+ If signup must always provision a runtime, you want Mode A — stop here and use
41
+ `vuilder-workspace-architecture`.
42
+
43
+ ## Surface shape (follow the Starter Choice Matrix; shell-first)
44
+
45
+ - **`tenant-app`** hosts marketing, native `/_mw` customer signup/login, and the
46
+ hosted product under `/app`. Browser customer auth uses `@minutework/web-auth`
47
+ against same-origin `/_mw/auth/*`; the principal is `tenant_customer`. `/_mw`
48
+ only resolves on a **live, canonical** customer-web host — go live with
49
+ `minutework deploy --live`. See `tenant-app-customer-auth-deploy/SKILL.md`.
50
+ - **The hosted broker/demo runs on the Vuilder's operator runtime**, not in the
51
+ browser. `/app` consumes it through `mw.query` / `mw.action` against
52
+ `webCustomerExposed` query/action manifests (see `app-pack-authoring/SKILL.md`
53
+ and `generated-workspace-architecture/SKILL.md`). Browser intake is untrusted:
54
+ it never chooses package refs, runtime providers, tenant ids, or install
55
+ coordinates.
56
+ - **`vuilder-shell`** remains the branded member/operator surface
57
+ (`/w/[workspace_slug]`) for the Vuilder's own operators and for customers once
58
+ they have their own runtime. See `shell-architecture/SKILL.md`. The hard
59
+ boundary still holds: the shell never owns identity, provisioning, or app-pack
60
+ install authority.
61
+
62
+ ## Shadow tenant + claim continuity
63
+
64
+ A Mode B customer exists as identity **before** they have their own runtime:
65
+
66
+ - When a visitor/customer first appears, Core resolves a **shadow tenant** and a
67
+ **shadow person** for their external identity (e.g. email). The shadow person
68
+ is a stable participation anchor, owned by the shadow tenant. See
69
+ `shadow-participation-and-guest-threads/SKILL.md`.
70
+ - Joining the host runtime via `/_mw` creates a customer membership on the
71
+ **host** tenant. Claim refs tie that membership back to the customer's shadow
72
+ identity, so history is preserved across the later spawn.
73
+ - The spawn is an **explicit claim/upgrade**, modeled as a real provisioning
74
+ step — never a silent mutation. The platform **promotes the customer's
75
+ existing tenant in place** rather than minting a fresh one, so there is no
76
+ duplicate identity and no orphaned history.
77
+
78
+ Do not invent a parallel guest-account or per-customer identity model; reuse the
79
+ external-identity → shadow tenant → shadow person → claim substrate.
80
+
81
+ ## The opt-in spawn action + configurable trigger
82
+
83
+ Spawn is **product-driven, not hardcoded**. There are two ways to fire it; both
84
+ target the same platform substrate (a `customer_runtime_spawn` onboarding intent
85
+ that promotes the customer's tenant in place and installs the Vuilder's
86
+ published app pack).
87
+
88
+ ### 1. Explicit opt-in action (available now)
89
+
90
+ Wire a "create my own runtime" affordance in `/app` to the platform's customer
91
+ spawn endpoint:
92
+
93
+ - The authenticated customer (`tenant_customer` session) POSTs to
94
+ `/_mw/runtime/spawn` on the live host.
95
+ - The platform gates on an **active, email-verified** customer membership,
96
+ resolves identity continuity, promotes the customer's tenant, and installs the
97
+ Vuilder's **published, attested** app pack. It is idempotent.
98
+ - The browser only signals intent. It never picks the package, runtime provider,
99
+ or tenant — the platform derives those from the host Vuilder + the customer's
100
+ verified identity.
101
+
102
+ This is the FleetRun-style "customer opts in" trigger *(illustrative)*.
103
+
104
+ ### 2. App-pack-declared condition (configurable trigger)
105
+
106
+ To make spawn fire when a **product condition** holds rather than on a button
107
+ press, declare the condition in the app pack instead of hardcoding it. Use the
108
+ local event bus declaration surface (`event-bus/SKILL.md`): emit a
109
+ product-defined event when the condition occurs, then declare an
110
+ `eventSubscription` (with `filters`) whose target flow requests the spawn. Keep
111
+ event types and field names vertical-neutral (they must pass `mw.E002`/`mw.E010`
112
+ — no vertical role/identifier words).
113
+
114
+ This is the Ostronaut-style "real data starts flowing" trigger *(illustrative)*:
115
+ emit a generic "data received" event, filter for the threshold that means the
116
+ customer is now operating for real, and let the subscription drive the spawn.
117
+
118
+ > Honesty note: the **declaration surface** (events, subscriptions, filters)
119
+ > ships today, and the **explicit opt-in action** above is fully executable. The
120
+ > automatic condition→spawn leg is delivered by platform substrate that is still
121
+ > being rolled out (a generic emit site, the flow→spawn dispatch, and the
122
+ > local-event dispatch flag). Until that lands in the target runtime, fall back
123
+ > to the explicit opt-in action and keep the declared condition as the
124
+ > product's source of truth. Do not assume auto-fire works without confirming it
125
+ > in `runtime-capability-inventory`.
126
+
127
+ ## Cross-runtime data continuity (scope honestly)
128
+
129
+ After a customer spawns their own runtime, what carries over?
130
+
131
+ - **Identity and shared references re-anchor via ontology Core URNs.** Promote
132
+ local facts to shared `core_urn`s and re-anchor them on the spawned runtime
133
+ via the reviewable promotion loop. See `ontology-authoring/SKILL.md` and
134
+ `runtime_ontology_contract.md`. This is the supported continuity primitive.
135
+ - **The spawn does not zero-copy the customer's host-runtime records into the
136
+ new runtime.** Ad-hoc record-level cross-runtime references (pointer + grant,
137
+ read at resolve time) are **not executable today**: `runtime_federation`
138
+ implements dataset publication + change-signal pub/sub only, and the
139
+ `bridge_protocol.md` hydrate path is design/spec, not built. So **a spawned
140
+ runtime cannot reference a specific record on the host runtime yet.** See
141
+ `federation_model.md` and `bridge_protocol.md`.
142
+ - **Therefore scope the product to: spawn starts fresh; shared identity
143
+ re-anchors via ontology URNs; deep history reference is a follow-on once the
144
+ federation record-reference primitive exists.** Do not promise zero-copy
145
+ history in product copy or design. If a Mode B product genuinely needs
146
+ record-level cross-runtime reads, report it as a capability gap
147
+ (`capability-gap-reporting/SKILL.md`) instead of inventing a copy-based
148
+ workaround.
149
+
150
+ ## Server-switcher across host + spawned runtime
151
+
152
+ After spawn, the customer holds **two memberships**: the customer membership on
153
+ the Vuilder's host runtime and the owner membership on their own spawned
154
+ runtime. Give them a way to switch between the hosted product and their own
155
+ runtime:
156
+
157
+ - Model this as multi-membership switching in the branded shell
158
+ (`shell-architecture/SKILL.md`) — each membership opens its own
159
+ `/w/[workspace_slug]` context; the shell never mixes their sessions.
160
+ - The host membership stays valid after spawn (it is the continuity ledger), so
161
+ the customer can keep using the shared hosted product and their own runtime
162
+ side by side.
163
+ - Identity stays single across both via the shared shadow/claim anchor; do not
164
+ create a second identity for the spawned runtime.
165
+
166
+ ## Related Skills
167
+
168
+ - `vuilder-workspace-architecture` — the base Vuilder shape and the Mode A
169
+ signup=auto-spawn flow this skill contrasts with.
170
+ - `tenant-app-customer-auth-deploy` — make `/_mw` customer auth resolve on a
171
+ live canonical host.
172
+ - `shadow-participation-and-guest-threads` — shadow tenant/person + claim
173
+ continuity for pre-runtime customers.
174
+ - `app-pack-authoring` and `generated-workspace-architecture` — `webCustomerExposed`
175
+ query/action manifests consumed by `/app` via `mw.query` / `mw.action`.
176
+ - `event-bus` (and `dataset-subscriber-flow`) — declarative event/subscription
177
+ surface for the configurable spawn trigger.
178
+ - `ontology-authoring` and `runtime_ontology_contract.md` — Core URN promotion
179
+ for cross-runtime identity continuity.
180
+ - `shell-architecture` — branded shell + multi-membership server switching.
181
+ - `federation_model.md` and `bridge_protocol.md` — what cross-runtime
182
+ federation does and does not support today (record-reference is a gap).
183
+ - `capability-gap-reporting` — report record-level cross-runtime read needs
184
+ rather than working around them.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vuilder-workspace-architecture
3
- description: "First skill for generated Vuilder workspaces: vuilder-app public site, vuilder-shell branded customer shell, app-pack source, and customer signup/install flow."
3
+ description: "First skill for generated Vuilder workspaces: vuilder-app public site, vuilder-shell branded customer shell, app-pack source, and the Mode A signup=auto-spawn flow. For hosted-demo-then-opt-in-spawn, see vuilder-mode-b-hosted-and-spawn."
4
4
  ---
5
5
 
6
6
  # Vuilder Workspace Architecture
@@ -9,6 +9,22 @@ Use this skill first when a generated workspace is a Vuilder workspace or when
9
9
  the request mentions Vuilder verticals, Vuilder public sites, branded tenant
10
10
  shells, customer vertical signup, or app-pack publishing for customer install.
11
11
 
12
+ ## Mode A vs Mode B — decide first
13
+
14
+ A Vuilder ships in one of two shapes; decide which before designing the
15
+ acquisition flow:
16
+
17
+ - **Mode A (signup = auto-spawn).** Signing up on the public site immediately
18
+ provisions the customer their own tenant runtime and installs the app pack.
19
+ This is the default this skill describes (see the Flow section below).
20
+ - **Mode B (hosted broker/demo, then opt-in spawn).** The Vuilder runs a shared
21
+ hosted product on its own operator runtime; customers join it via `/_mw` and
22
+ use it there, then provision their OWN runtime later as an opt-in step (with a
23
+ configurable trigger). If customers should try a hosted product before getting
24
+ their own server, it is Mode B — **read
25
+ `vuilder-mode-b-hosted-and-spawn/SKILL.md`** and follow it instead of the Mode
26
+ A flow below.
27
+
12
28
  ## Default Workspace Shape
13
29
 
14
30
  A first-class Vuilder workspace is vertical-neutral. FleetRun is an example
@@ -31,9 +47,10 @@ Expected generated layout:
31
47
  metadata under the workspace authoring layer.
32
48
  - Optional `sidecar/` and `mobile/` starters when selected.
33
49
 
34
- ## Flow
50
+ ## Flow (Mode A)
35
51
 
36
- The acquisition and install path is:
52
+ The Mode A acquisition and install path is (for Mode B, follow
53
+ `vuilder-mode-b-hosted-and-spawn/SKILL.md` instead):
37
54
 
38
55
  1. Customer lands on the Vuilder public site (`vuilder-app`).
39
56
  2. The public-site BFF creates `customer_vertical_signup` using
@@ -76,3 +93,6 @@ billing policy, or install coordinates.
76
93
  marketplace publish output.
77
94
  - Use `generated-workspace-architecture` for general local workspace trust
78
95
  boundaries.
96
+ - Use `vuilder-mode-b-hosted-and-spawn` when the Vuilder runs a hosted
97
+ broker/demo customers join first and lets them spawn their own runtime later
98
+ (Mode B), instead of the Mode A signup=auto-spawn flow above.
@@ -1,7 +1,9 @@
1
1
  NEXT_PUBLIC_MW_APP_ID=tenant.app
2
2
  MW_TEMPLATE_APP_NAME=Tenant App
3
3
  MW_PUBLIC_BASE_URL=
4
- # Only needed when hosting this app off-platform (Vercel / custom domain). Set to the
5
- # MinuteWork platform gateway base URL to transparently proxy same-origin /_mw/* customer
6
- # auth to the gateway. Leave blank for managed-subdomain hosts (gateway-fronted).
4
+ # Only needed when hosting this app off-platform (Vercel / custom domain) or
5
+ # running local next dev against a live customer-web binding. Set this to the
6
+ # canonical live customer-web host returned by `minutework deploy --live`, such as
7
+ # https://<label>.customers.dev.minutework.ai. Do not set it to bare
8
+ # https://dev.minutework.ai.
7
9
  MW_GATEWAY_BASE_URL=
@@ -64,6 +64,21 @@ runtime-command demo, or a server-only public-content token adapter.
64
64
  defaults to `tenant.app`
65
65
  - `MW_TEMPLATE_APP_NAME` controls the display name and defaults to `Tenant App`
66
66
  - `MW_PUBLIC_BASE_URL` is optional and only affects metadata routes
67
+ - `MW_GATEWAY_BASE_URL` is only needed when the app is not directly
68
+ gateway-fronted. For local auth against dev, set it to the canonical live
69
+ customer-web host returned by `minutework deploy --live`, for example
70
+ `https://<label>.customers.dev.minutework.ai`. Do not set it to bare
71
+ `https://dev.minutework.ai`; `/_mw` auth is resolved from the live
72
+ customer-web host.
73
+
74
+ Local real-auth dev loop:
75
+
76
+ 1. `export MW_CLI_PLATFORM_BASE_URL=https://dev.minutework.ai`
77
+ 2. `minutework login --platform https://dev.minutework.ai`
78
+ 3. `minutework link --runtime --sandbox`
79
+ 4. `minutework deploy --live`
80
+ 5. set `MW_GATEWAY_BASE_URL` to the returned `*.customers.dev.minutework.ai`
81
+ live host, then run local `next dev`.
67
82
 
68
83
  ## Validation
69
84
 
@@ -22,11 +22,11 @@ function resolveTurbopackRoot(startDirectory) {
22
22
 
23
23
  // Bring-your-own host support: when this tenant-app is hosted off-platform (Vercel
24
24
  // or a custom domain) instead of being fronted by the MinuteWork gateway, set
25
- // MW_GATEWAY_BASE_URL so same-origin `/_mw/*` customer-auth calls are transparently
26
- // proxied to the platform gateway. The gateway serves customer auth for this tenant's
27
- // live canonical customer-web host (provisioned via `minutework deploy --live`), so
28
- // @minutework/web-auth keeps its same-origin contract without a remote project URL.
29
- // Unset by default: managed-subdomain hosts are gateway-fronted and need no rewrite.
25
+ // MW_GATEWAY_BASE_URL to the live canonical customer-web host returned by
26
+ // `minutework deploy --live`. The gateway serves customer auth only for that
27
+ // host, so local dev should point at e.g. https://<label>.customers.dev.minutework.ai,
28
+ // not the bare platform origin. Unset by default: managed-subdomain hosts are
29
+ // gateway-fronted and need no rewrite.
30
30
  const gatewayBaseUrl = (process.env.MW_GATEWAY_BASE_URL || "").trim().replace(/\/+$/, "");
31
31
 
32
32
  const nextConfig = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minutework",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "description": "MinuteWork CLI for workspace scaffolding, local preview workflows, and hosted preview deploys.",
5
5
  "type": "module",
6
6
  "bin": {