minutework 0.1.29 → 0.1.31
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/EXTERNAL_ALPHA.md +33 -33
- package/README.md +35 -33
- package/assets/claude-local/CLAUDE.md.template +12 -12
- package/assets/claude-local/skills/README.md +1 -1
- package/assets/claude-local/skills/app-pack-authoring/SKILL.md +3 -3
- package/assets/claude-local/skills/capability-gap-reporting/SKILL.md +3 -3
- package/assets/claude-local/skills/generated-workspace-architecture/SKILL.md +4 -3
- package/assets/claude-local/skills/layering-and-import-modes/SKILL.md +2 -2
- package/assets/claude-local/skills/openclaw-skill-importer/SKILL.md +2 -2
- package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +8 -8
- package/assets/claude-local/skills/published-web-and-mw-core-site/SKILL.md +2 -2
- package/assets/claude-local/skills/runtime-capability-inventory/SKILL.md +6 -1
- package/assets/claude-local/skills/standalone-mobile-client/SKILL.md +8 -1
- package/assets/claude-local/skills/vuilder-discovery-output-contract/SKILL.md +6 -6
- package/assets/claude-local/skills/workspace-guidance-refresh/SKILL.md +4 -4
- package/assets/templates/fastapi-sidecar/pyproject.toml +1 -1
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +1 -1
- package/assets/templates/mobile-app/.env.example +7 -5
- package/assets/templates/mobile-app/AGENTS.md +8 -3
- package/assets/templates/mobile-app/README.md +22 -16
- package/assets/templates/mobile-app/app/(app)/_layout.tsx +2 -2
- package/assets/templates/mobile-app/app/(app)/index.tsx +2 -2
- package/assets/templates/mobile-app/app/(auth)/login.tsx +3 -3
- package/assets/templates/mobile-app/app/_layout.tsx +1 -1
- package/assets/templates/mobile-app/app.json +0 -3
- package/assets/templates/mobile-app/babel.config.js +1 -1
- package/assets/templates/mobile-app/eas.json +1 -1
- package/assets/templates/mobile-app/expo-env.d.ts +1 -1
- package/assets/templates/mobile-app/metro.config.js +12 -2
- package/assets/templates/mobile-app/package.json +19 -15
- package/assets/templates/mobile-app/src/mw/client.ts +3 -3
- package/assets/templates/mobile-app/src/mw/contracts.ts +2 -2
- package/assets/templates/mobile-app/src/mw/endpoints.ts +2 -2
- package/assets/templates/mobile-app/src/mw/env.ts +13 -5
- package/assets/templates/mobile-app/src/mw/session.ts +1 -1
- package/assets/templates/mobile-app/template.json +1 -1
- package/assets/templates/mobile-app/tools/template/validate-template.mjs +2 -2
- package/assets/templates/mobile-app/tsconfig.json +1 -1
- package/assets/templates/next-tenant-app/.env.example +1 -1
- package/assets/templates/next-tenant-app/README.md +3 -3
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/app/app/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/app/page.tsx +1 -1
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/login/page.test.ts +1 -1
- package/assets/templates/next-tenant-app/src/app/login/page.tsx +1 -1
- package/assets/templates/next-tenant-app/src/app/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +14 -14
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +3 -3
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +1 -1
- package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +3 -3
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +1 -1
- package/assets/templates/next-tenant-app/src/lib/public-site.test.ts +1 -1
- package/assets/templates/next-tenant-app/tools/template/with-public-site-fixture.mjs +2 -2
- package/bin/minutework.js +1 -1
- package/dist/agent.js +7 -7
- package/dist/agent.js.map +1 -1
- package/dist/auth.js +7 -7
- package/dist/auth.js.map +1 -1
- package/dist/compile.js +5 -5
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/deploy.js +7 -7
- package/dist/deploy.js.map +1 -1
- package/dist/developer-client.js +2 -2
- package/dist/developer-client.js.map +1 -1
- package/dist/index.js +31 -28
- package/dist/index.js.map +1 -1
- package/dist/init.js +24 -27
- package/dist/init.js.map +1 -1
- package/dist/launcher.js +1 -1
- package/dist/launcher.js.map +1 -1
- package/dist/managed-engine.js +6 -6
- package/dist/managed-engine.js.map +1 -1
- package/dist/orchestrator-context.js +1 -1
- package/dist/orchestrator-context.js.map +1 -1
- package/dist/orchestrator.js +15 -15
- package/dist/orchestrator.js.map +1 -1
- package/dist/paths.js +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/publish.js +3 -3
- package/dist/publish.js.map +1 -1
- package/dist/reporting.js +8 -8
- package/dist/reporting.js.map +1 -1
- package/dist/sandbox.js +5 -5
- package/dist/sandbox.js.map +1 -1
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/tokens.js +9 -9
- package/dist/tokens.js.map +1 -1
- package/dist/workspace-assets.js +6 -6
- package/dist/workspace-assets.js.map +1 -1
- package/dist/workspace.js +3 -3
- package/dist/workspace.js.map +1 -1
- package/package.json +4 -3
- package/vendor/workspace-mcp/context.d.ts +6 -6
- package/vendor/workspace-mcp/context.js +56 -56
- package/vendor/workspace-mcp/context.js.map +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vuilder-discovery-output-contract
|
|
3
|
-
description: "Constrain Vuilder discovery to AI-native service operations and
|
|
3
|
+
description: "Constrain Vuilder discovery to AI-native service operations and PandaWork-buildable delivery systems instead of generic startup ideas."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Vuilder Discovery Output Contract
|
|
@@ -22,7 +22,7 @@ Each card must describe:
|
|
|
22
22
|
- an AI-native service outcome the operator can credibly deliver
|
|
23
23
|
- the buyer or internal team receiving that service outcome
|
|
24
24
|
- evidence from the user's profile that makes the operator credible
|
|
25
|
-
- the
|
|
25
|
+
- the PandaWork delivery system Builder can prepare
|
|
26
26
|
- the first workflow the system should support
|
|
27
27
|
- the runtime records, AI workers, Builder surfaces, and artifacts involved
|
|
28
28
|
- capability gap candidates for unsupported substrate
|
|
@@ -30,7 +30,7 @@ Each card must describe:
|
|
|
30
30
|
Discovery should ask:
|
|
31
31
|
|
|
32
32
|
> What service outcome can this operator credibly deliver, and what
|
|
33
|
-
>
|
|
33
|
+
> PandaWork-supported system can Builder create to help deliver it?
|
|
34
34
|
|
|
35
35
|
Do not ask:
|
|
36
36
|
|
|
@@ -38,7 +38,7 @@ Do not ask:
|
|
|
38
38
|
|
|
39
39
|
## Builder Constraints
|
|
40
40
|
|
|
41
|
-
- Compose shared
|
|
41
|
+
- Compose shared PandaWork substrate before bespoke code.
|
|
42
42
|
- Treat the app pack as the shipped product unit.
|
|
43
43
|
- Check shell fit first for member-facing collaboration and operator work.
|
|
44
44
|
- Use `tenant-app` only for public surfaces or explicit standalone UI
|
|
@@ -72,7 +72,7 @@ cards before it saves proposal fields:
|
|
|
72
72
|
|
|
73
73
|
- `extract_workflows_from_context` for repeatable work, bottlenecks, buyers, and
|
|
74
74
|
AI workforce jobs already implied by the user's context.
|
|
75
|
-
- `search_industry_examples` for curated
|
|
75
|
+
- `search_industry_examples` for curated PandaWork service-business patterns.
|
|
76
76
|
This is not open web search.
|
|
77
77
|
- `estimate_market_pricing` for bounded pilot and retainer ranges with explicit
|
|
78
78
|
assumptions and uncertainty.
|
|
@@ -125,7 +125,7 @@ Use the `DiscoveryBuildCardV1` shape:
|
|
|
125
125
|
- `paid_blueprint_will_create`
|
|
126
126
|
- optional `service_packaging`
|
|
127
127
|
|
|
128
|
-
Plain-language fields are user-facing. They must express
|
|
128
|
+
Plain-language fields are user-facing. They must express PandaWork's loop:
|
|
129
129
|
build the AI workforce from work the operator already does, use it first under
|
|
130
130
|
their own judgment, then sell it back to their industry. Do not expose Builder
|
|
131
131
|
jargon such as app pack, schemas, runtime records, right rail, runtime agent seed,
|
|
@@ -7,13 +7,13 @@ description: "Exported guidance looks stale, a newly added skill is missing, or
|
|
|
7
7
|
|
|
8
8
|
Use this skill when the generated workspace guidance looks stale, a newly added
|
|
9
9
|
Builder skill is missing from the local workspace, or `CLAUDE.md` / MCP wiring
|
|
10
|
-
does not match the current
|
|
10
|
+
does not match the current PandaWork CLI export.
|
|
11
11
|
|
|
12
|
-
- From the generated workspace root, run `
|
|
12
|
+
- From the generated workspace root, run `pandawork workspace sync-assets`.
|
|
13
13
|
- To preview drift without writing files, run
|
|
14
|
-
`
|
|
14
|
+
`pandawork workspace sync-assets --check`.
|
|
15
15
|
- To overwrite conflicting managed files, run
|
|
16
|
-
`
|
|
16
|
+
`pandawork workspace sync-assets --force`.
|
|
17
17
|
- This command refreshes the managed guidance surface only:
|
|
18
18
|
- `CLAUDE.md`
|
|
19
19
|
- `skills/**`
|
|
@@ -8,7 +8,7 @@ packages = [{ include = "fastapi_sidecar", from = "src" }]
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "fastapi-sidecar-template"
|
|
10
10
|
version = "0.1.0"
|
|
11
|
-
description = "Canonical FastAPI internal sidecar scaffold for
|
|
11
|
+
description = "Canonical FastAPI internal sidecar scaffold for PandaWork Builder."
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.12,<4.0"
|
|
14
14
|
dependencies = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
# DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
2
2
|
#
|
|
3
3
|
# Copy this file to `.env` and set the values for your environment.
|
|
4
4
|
#
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
# the platform issues short-lived bearer tokens at runtime via the native
|
|
9
9
|
# device flow.
|
|
10
10
|
|
|
11
|
-
# Base URL of the
|
|
12
|
-
#
|
|
11
|
+
# Base URL of the PandaWork platform this app talks to directly.
|
|
12
|
+
# Local dev defaults to http://127.0.0.1:8000 when this is omitted, but physical
|
|
13
|
+
# devices usually need your computer's LAN URL or a tunneled/dev platform URL.
|
|
14
|
+
# The app calls /api/v1/native/... here.
|
|
13
15
|
EXPO_PUBLIC_MW_PLATFORM_BASE_URL=https://<your-platform-base-url>
|
|
14
16
|
|
|
15
|
-
# Optional display name shown in the UI. Defaults to "
|
|
16
|
-
# EXPO_PUBLIC_MW_APP_NAME=
|
|
17
|
+
# Optional display name shown in the UI. Defaults to "PandaWork".
|
|
18
|
+
# EXPO_PUBLIC_MW_APP_NAME=PandaWork
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# AGENTS.md — mobile-app starter
|
|
2
2
|
|
|
3
3
|
You are working in a **bring-your-own-UI Expo (React Native + Expo Router)**
|
|
4
|
-
app. **You own all UI/UX.** The only
|
|
4
|
+
app. **You own all UI/UX.** The only PandaWork-managed code is the thin
|
|
5
5
|
substrate under `src/mw/`.
|
|
6
6
|
|
|
7
7
|
## The one rule
|
|
8
8
|
|
|
9
|
-
**Only `src/mw/` is
|
|
9
|
+
**Only `src/mw/` is PandaWork substrate.** Build your product in `app/` and your
|
|
10
10
|
own components/modules. Do not move product logic into `src/mw/`, and do not
|
|
11
11
|
build a parallel/local auth stack — the platform owns identity. The mobile app
|
|
12
12
|
is a **direct platform native API client** (bearer token to `/api/v1/native/...`),
|
|
@@ -25,7 +25,7 @@ For the native craft (UI, data, build/release), lean on your local IDE skills:
|
|
|
25
25
|
- `upgrading-expo` — SDK upgrades and dependency fixes
|
|
26
26
|
- `expo-cicd-workflows` — EAS build/deploy pipelines (`.eas/workflows/`)
|
|
27
27
|
|
|
28
|
-
##
|
|
28
|
+
## PandaWork integration shape
|
|
29
29
|
|
|
30
30
|
For how this app fits the platform (the standalone-client exception, the native
|
|
31
31
|
session token, and the device flow), read the Builder skill
|
|
@@ -42,3 +42,8 @@ browser-assisted PKCE device flow against the platform native session endpoints
|
|
|
42
42
|
`expo-secure-store`. Wire your UI against the documented client methods
|
|
43
43
|
(`authorize` -> `exchange`, `loadSession`, `logout`). Set `app.json` `expo.scheme`
|
|
44
44
|
to your own unique scheme — that is the OAuth-style redirect target.
|
|
45
|
+
|
|
46
|
+
The starter is standalone npm-owned app code, even when generated beside
|
|
47
|
+
`tenant-app` in a root pnpm workspace. Run mobile commands from `mobile/` with
|
|
48
|
+
`npm install` and `npx expo start`; do not add `mobile` to the root
|
|
49
|
+
`pnpm-workspace.yaml`.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Mobile App Starter (Expo, bring-your-own-UI)
|
|
2
2
|
|
|
3
3
|
A minimal **Expo (React Native + Expo Router)** starter for building a native
|
|
4
|
-
|
|
4
|
+
PandaWork client. **You own all of the UI/UX.** The only PandaWork-managed
|
|
5
5
|
code is the thin substrate under `src/mw/`. Everything else in this template is
|
|
6
6
|
a deliberately plain placeholder meant to be replaced.
|
|
7
7
|
|
|
8
|
-
There is **no
|
|
8
|
+
There is **no PandaWork design system here** — bring your own. Style with
|
|
9
9
|
whatever you like (plain `StyleSheet`, NativeWind/Tailwind, Tamagui, etc.). The
|
|
10
10
|
plain screens use `StyleSheet` only so there is nothing to rip out.
|
|
11
11
|
|
|
@@ -13,17 +13,17 @@ plain screens use `StyleSheet` only so there is nothing to rip out.
|
|
|
13
13
|
|
|
14
14
|
| Path | Owner | Notes |
|
|
15
15
|
| --- | --- | --- |
|
|
16
|
-
| `src/mw/env.ts` | **
|
|
17
|
-
| `src/mw/endpoints.ts` | **
|
|
18
|
-
| `src/mw/contracts.ts` | **
|
|
19
|
-
| `src/mw/client.ts` | **
|
|
20
|
-
| `src/mw/session.ts` | **
|
|
21
|
-
| `tools/template/` | **
|
|
16
|
+
| `src/mw/env.ts` | **PandaWork substrate** | Validates `EXPO_PUBLIC_MW_PLATFORM_BASE_URL` (+ optional app name) |
|
|
17
|
+
| `src/mw/endpoints.ts` | **PandaWork substrate** | Builds platform `/api/v1/native/...` URLs |
|
|
18
|
+
| `src/mw/contracts.ts` | **PandaWork substrate** | Zod schemas for native session + token payloads |
|
|
19
|
+
| `src/mw/client.ts` | **PandaWork substrate** | Native token client — real browser-assisted PKCE device flow |
|
|
20
|
+
| `src/mw/session.ts` | **PandaWork substrate** | Secure-store token wrapper (`expo-secure-store`) |
|
|
21
|
+
| `tools/template/` | **PandaWork substrate** | Template-governance tooling, not shipped app code |
|
|
22
22
|
| `app/**` | **You** | Expo Router screens — replace freely |
|
|
23
23
|
| `package.json`, `app.json`, `eas.json` | **You** | App config — replace freely |
|
|
24
24
|
| `tsconfig.json`, `babel.config.js`, `metro.config.js` | **You** | Tooling config — replace freely |
|
|
25
25
|
|
|
26
|
-
Rule of thumb: **only `src/mw/` is
|
|
26
|
+
Rule of thumb: **only `src/mw/` is PandaWork substrate.** If you find yourself
|
|
27
27
|
editing `src/mw/` to add product behavior, that behavior probably belongs in
|
|
28
28
|
your own `app/` / components instead.
|
|
29
29
|
|
|
@@ -84,7 +84,10 @@ The full flow is documented in the doc-comment at the top of `src/mw/client.ts`.
|
|
|
84
84
|
|
|
85
85
|
## Environment
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
Fresh local development works without a `.env`: `src/mw/env.ts` defaults
|
|
88
|
+
`EXPO_PUBLIC_MW_PLATFORM_BASE_URL` to `http://127.0.0.1:8000` so the app can
|
|
89
|
+
boot immediately after install. For a physical device, a deployed platform, or
|
|
90
|
+
anything you plan to ship, copy `.env.example` to `.env` and set:
|
|
88
91
|
|
|
89
92
|
```
|
|
90
93
|
EXPO_PUBLIC_MW_PLATFORM_BASE_URL=https://<your-platform-base-url>
|
|
@@ -92,24 +95,27 @@ EXPO_PUBLIC_MW_PLATFORM_BASE_URL=https://<your-platform-base-url>
|
|
|
92
95
|
|
|
93
96
|
Only `EXPO_PUBLIC_*` variables are bundled into the app, and they are **not
|
|
94
97
|
secret** — never put keys/tokens in them. `src/mw/env.ts` validates this value
|
|
95
|
-
at startup with zod
|
|
98
|
+
at startup with zod.
|
|
96
99
|
|
|
97
100
|
## Running locally
|
|
98
101
|
|
|
99
102
|
```
|
|
100
|
-
npm install
|
|
101
|
-
|
|
103
|
+
npm install
|
|
104
|
+
npx expo start # Expo dev server (then press i / a, or scan with Expo Go)
|
|
102
105
|
npm run ios
|
|
103
106
|
npm run android
|
|
104
107
|
npm run typecheck # tsc --noEmit
|
|
105
108
|
```
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
110
|
+
This starter is pinned to the current Expo SDK 56 line so the store Expo Go app
|
|
111
|
+
can load it for UI smoke testing. The native auth flow opens a system browser
|
|
112
|
+
and returns to your custom app scheme, so real sign-in testing needs a custom
|
|
113
|
+
development client rather than stock Expo Go; see the `expo-dev-client` IDE
|
|
114
|
+
skill.
|
|
109
115
|
|
|
110
116
|
## Distribution
|
|
111
117
|
|
|
112
|
-
**Distribution is your EAS pipeline, not `
|
|
118
|
+
**Distribution is your EAS pipeline, not `pandawork deploy`.** This starter is
|
|
113
119
|
not a hosted web/sidecar deployable; it produces native binaries. Build and ship
|
|
114
120
|
with EAS (`eas build`, `eas submit`, EAS Update). `eas.json` ships minimal
|
|
115
121
|
`preview` and `production` profiles to start from. See the `expo-deployment` and
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
2
2
|
//
|
|
3
|
-
// Authed area layout. This is where you'd guard on a loaded
|
|
3
|
+
// Authed area layout. This is where you'd guard on a loaded PandaWork session
|
|
4
4
|
// (via `mwClient.loadSession()`) and redirect to /(auth)/login when there is no
|
|
5
5
|
// valid token. Left as a plain Stack so you can build your own gating/UX.
|
|
6
6
|
import { Stack } from "expo-router";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
2
2
|
//
|
|
3
3
|
// Trivial authed screen. Replace with your real product home. Build your data
|
|
4
4
|
// fetching against the platform native API using the bearer token from
|
|
@@ -21,7 +21,7 @@ export default function HomeScreen() {
|
|
|
21
21
|
<View style={styles.container}>
|
|
22
22
|
<Text style={styles.title}>You are in.</Text>
|
|
23
23
|
<Text style={styles.body}>
|
|
24
|
-
Replace this screen with your product. Only `src/mw/` is
|
|
24
|
+
Replace this screen with your product. Only `src/mw/` is PandaWork
|
|
25
25
|
substrate — everything else is yours.
|
|
26
26
|
</Text>
|
|
27
27
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
2
2
|
//
|
|
3
3
|
// This screen is intentionally plain and is meant to be REWRITTEN. It exists to
|
|
4
|
-
// show the one integration seam you care about: kicking off
|
|
4
|
+
// show the one integration seam you care about: kicking off PandaWork's
|
|
5
5
|
// browser-assisted native sign-in through `src/mw/client.ts`.
|
|
6
6
|
//
|
|
7
7
|
// Pressing "Sign in" runs the real device flow: authorize in a system browser ->
|
|
@@ -50,7 +50,7 @@ export default function LoginScreen() {
|
|
|
50
50
|
]}
|
|
51
51
|
>
|
|
52
52
|
<Text style={styles.buttonText}>
|
|
53
|
-
{busy ? "Opening sign in…" : "Sign in with
|
|
53
|
+
{busy ? "Opening sign in…" : "Sign in with PandaWork"}
|
|
54
54
|
</Text>
|
|
55
55
|
</Pressable>
|
|
56
56
|
</View>
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is MinuteWork substrate.",
|
|
3
|
-
"//scheme": "expo.scheme is the OAuth-style redirect target for the native auth device flow (src/mw/client.ts builds <scheme>://auth/native-callback). Set a unique scheme before shipping.",
|
|
4
2
|
"expo": {
|
|
5
3
|
"name": "mobile-app",
|
|
6
4
|
"slug": "mobile-app",
|
|
@@ -8,7 +6,6 @@
|
|
|
8
6
|
"version": "0.1.0",
|
|
9
7
|
"orientation": "portrait",
|
|
10
8
|
"userInterfaceStyle": "automatic",
|
|
11
|
-
"newArchEnabled": true,
|
|
12
9
|
"ios": {
|
|
13
10
|
"supportsTablet": true,
|
|
14
11
|
"bundleIdentifier": "com.example.mobileapp"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
2
|
+
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate. Distribution is YOUR EAS pipeline, not `pandawork deploy`.",
|
|
3
3
|
"cli": {
|
|
4
4
|
"version": ">= 12.0.0",
|
|
5
5
|
"appVersionSource": "remote"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="expo/types" />
|
|
2
2
|
|
|
3
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
3
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
4
4
|
// NOTE: This file should not be edited and should be committed; Expo regenerates
|
|
5
5
|
// it. It gives `process.env.EXPO_PUBLIC_*` string typings for `src/mw/env.ts`.
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
// DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
2
|
-
//
|
|
1
|
+
// DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.
|
|
2
|
+
// Keep Metro scoped to this standalone Expo app even when the generated
|
|
3
|
+
// PandaWork workspace root also has a pnpm workspace for tenant-app.
|
|
4
|
+
const path = require("node:path");
|
|
3
5
|
const { getDefaultConfig } = require("expo/metro-config");
|
|
4
6
|
|
|
5
7
|
const config = getDefaultConfig(__dirname);
|
|
6
8
|
|
|
9
|
+
config.projectRoot = __dirname;
|
|
10
|
+
config.watchFolders = [];
|
|
11
|
+
config.resolver = {
|
|
12
|
+
...config.resolver,
|
|
13
|
+
disableHierarchicalLookup: true,
|
|
14
|
+
nodeModulesPaths: [path.join(__dirname, "node_modules")],
|
|
15
|
+
};
|
|
16
|
+
|
|
7
17
|
module.exports = config;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is
|
|
2
|
+
"//": "DEVELOPER-OWNED — replace freely. Only src/mw/ is PandaWork substrate.",
|
|
3
3
|
"name": "mobile-app",
|
|
4
4
|
"version": "0.1.0",
|
|
5
5
|
"private": true,
|
|
@@ -11,22 +11,26 @@
|
|
|
11
11
|
"typecheck": "tsc --noEmit"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"expo": "~
|
|
15
|
-
"expo
|
|
16
|
-
"expo-
|
|
17
|
-
"expo-
|
|
18
|
-
"expo-
|
|
19
|
-
"expo-
|
|
20
|
-
"expo-
|
|
21
|
-
"expo-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"react
|
|
25
|
-
"react-
|
|
14
|
+
"@expo/metro-runtime": "~56.0.13",
|
|
15
|
+
"expo": "~56.0.8",
|
|
16
|
+
"expo-asset": "~56.0.15",
|
|
17
|
+
"expo-constants": "~56.0.16",
|
|
18
|
+
"expo-crypto": "~56.0.4",
|
|
19
|
+
"expo-linking": "~56.0.13",
|
|
20
|
+
"expo-router": "~56.2.8",
|
|
21
|
+
"expo-secure-store": "~56.0.4",
|
|
22
|
+
"expo-status-bar": "~56.0.4",
|
|
23
|
+
"expo-web-browser": "~56.0.5",
|
|
24
|
+
"react": "19.2.3",
|
|
25
|
+
"react-dom": "19.2.3",
|
|
26
|
+
"react-native": "0.85.3",
|
|
27
|
+
"react-native-safe-area-context": "~5.8.0",
|
|
28
|
+
"react-native-screens": "~4.25.2",
|
|
29
|
+
"react-native-web": "^0.21.2",
|
|
26
30
|
"zod": "^3.23.8"
|
|
27
31
|
},
|
|
28
32
|
"devDependencies": {
|
|
29
|
-
"@types/react": "~
|
|
30
|
-
"typescript": "~
|
|
33
|
+
"@types/react": "~19.2.14",
|
|
34
|
+
"typescript": "~6.0.3"
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
3
|
+
// PandaWork native token client. Implements the browser-assisted device flow
|
|
4
4
|
// against the SHIPPED platform native-token endpoints (`/api/v1/native/session/*`).
|
|
5
5
|
//
|
|
6
|
-
// Authentication is owned by the
|
|
6
|
+
// Authentication is owned by the PandaWork platform. This client only *obtains
|
|
7
7
|
// and uses* a platform-issued bearer token — there is NO JWT minting, NO password
|
|
8
8
|
// handling, NO local user table, and NO parallel auth stack here. Token plaintext
|
|
9
9
|
// is never logged.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
// Zod schemas for the
|
|
3
|
+
// Zod schemas for the PandaWork platform *native* session payloads. These match
|
|
4
4
|
// the SHIPPED platform native-token slice (`/api/v1/native/session/*`) response
|
|
5
5
|
// shapes exactly (DRF emits snake_case). They describe API responses, not product
|
|
6
6
|
// data. Keep them aligned with the platform serializers in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
|
-
// Builds absolute URLs for the
|
|
3
|
+
// Builds absolute URLs for the PandaWork *platform native* session endpoints.
|
|
4
4
|
//
|
|
5
5
|
// These endpoints are the DIRECT platform API surface for native clients
|
|
6
6
|
// (`/api/v1/native/...`). The mobile app authenticates with a platform-issued
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
3
|
// Validates the EXPO_PUBLIC_* configuration the mobile app needs to talk to the
|
|
4
|
-
//
|
|
4
|
+
// PandaWork platform. Mirrors the spirit of the next-tenant-app
|
|
5
5
|
// `env.server.ts`, but for Expo public env: in Expo, only `EXPO_PUBLIC_*`
|
|
6
6
|
// variables are inlined into the client bundle, and they must be referenced as
|
|
7
7
|
// *static* `process.env.EXPO_PUBLIC_FOO` property accesses so the Expo bundler
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import { z } from "zod";
|
|
15
15
|
|
|
16
|
+
const DEFAULT_LOCAL_PLATFORM_BASE_URL = "http://127.0.0.1:8000";
|
|
17
|
+
|
|
16
18
|
const baseUrlSchema = z.preprocess((value) => {
|
|
17
19
|
if (typeof value !== "string") {
|
|
18
20
|
return value;
|
|
@@ -27,16 +29,22 @@ const optionalNameSchema = z.preprocess((value) => {
|
|
|
27
29
|
}
|
|
28
30
|
const normalized = value.trim();
|
|
29
31
|
return normalized.length > 0 ? normalized : undefined;
|
|
30
|
-
}, z.string().min(1).default("
|
|
32
|
+
}, z.string().min(1).default("PandaWork"));
|
|
31
33
|
|
|
32
34
|
const envSchema = z.object({
|
|
33
35
|
platformBaseUrl: baseUrlSchema,
|
|
34
36
|
appName: optionalNameSchema,
|
|
35
37
|
});
|
|
36
38
|
|
|
39
|
+
const configuredPlatformBaseUrl = process.env.EXPO_PUBLIC_MW_PLATFORM_BASE_URL;
|
|
40
|
+
|
|
37
41
|
const parsed = envSchema.safeParse({
|
|
38
42
|
// Static accesses so the Expo bundler can inline these at build time.
|
|
39
|
-
platformBaseUrl:
|
|
43
|
+
platformBaseUrl:
|
|
44
|
+
typeof configuredPlatformBaseUrl === "string" &&
|
|
45
|
+
configuredPlatformBaseUrl.trim().length > 0
|
|
46
|
+
? configuredPlatformBaseUrl
|
|
47
|
+
: DEFAULT_LOCAL_PLATFORM_BASE_URL,
|
|
40
48
|
appName: process.env.EXPO_PUBLIC_MW_APP_NAME,
|
|
41
49
|
});
|
|
42
50
|
|
|
@@ -50,7 +58,7 @@ if (!parsed.success) {
|
|
|
50
58
|
|
|
51
59
|
throw new Error(
|
|
52
60
|
`Invalid Expo public environment for mobile-app: ${issues}. ` +
|
|
53
|
-
"
|
|
61
|
+
"Set EXPO_PUBLIC_MW_PLATFORM_BASE_URL to the PandaWork platform URL.",
|
|
54
62
|
);
|
|
55
63
|
}
|
|
56
64
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate. Thin layer — do not put product UI/logic here.
|
|
2
2
|
//
|
|
3
3
|
// Secure-store wrapper for the platform-issued native token pair. Persists the
|
|
4
4
|
// `{access, refresh, expiresAt}` triple in the device keychain/keystore via
|
|
@@ -14,5 +14,5 @@
|
|
|
14
14
|
"reference/mwv3-dj6-docs/auth_and_credential_contract.md"
|
|
15
15
|
],
|
|
16
16
|
"deployable": false,
|
|
17
|
-
"notes": "Bring-your-own-UI Expo (React Native + Expo Router) starter. Direct platform native API client (bearer token to /api/v1/native/...), NOT a tenant-app BFF cookie client. Distribution is the developer's EAS pipeline, not `
|
|
17
|
+
"notes": "Bring-your-own-UI Expo (React Native + Expo Router) starter. Direct platform native API client (bearer token to /api/v1/native/...), NOT a tenant-app BFF cookie client. Distribution is the developer's EAS pipeline, not `pandawork deploy`. Only src/mw/ is PandaWork substrate; everything else is developer-owned. src/mw/client.ts implements the real browser-assisted PKCE device flow against the platform native session endpoints; the OAuth-style redirect target is the app.json expo.scheme. This manifest is validated by tools/template/validate-template.mjs, not the strict shared template.schema.json (mobile is not a web/sidecar deployable kind)."
|
|
18
18
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// PandaWork substrate — template governance tool (not part of the shipped app).
|
|
2
2
|
//
|
|
3
3
|
// Validates this template's `template.json`. The mobile starter is NOT a
|
|
4
4
|
// web/sidecar deployable, so it intentionally does NOT validate against the
|
|
@@ -55,7 +55,7 @@ if (manifest.builder_edit_mode !== "workspace_copy_only") {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (manifest.deployable !== false) {
|
|
58
|
-
throw new Error("mobile-app must declare deployable: false (EAS pipeline, not `
|
|
58
|
+
throw new Error("mobile-app must declare deployable: false (EAS pipeline, not `pandawork deploy`)");
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
if (!Array.isArray(manifest.required_bootstrap_steps)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
MW_PLATFORM_BASE_URL=http://127.0.0.1:8000
|
|
2
2
|
MW_PUBLIC_CONTENT_SOURCE=none
|
|
3
3
|
MW_CONTENT_API_TOKEN=
|
|
4
|
-
MW_TEMPLATE_APP_NAME=
|
|
4
|
+
MW_TEMPLATE_APP_NAME=PandaWork Combined Starter
|
|
5
5
|
MW_PUBLIC_BASE_URL=
|
|
6
6
|
MW_PUBLIC_SITE_PROPERTY_KEY=
|
|
7
7
|
MW_PUBLIC_SITE_ENV=preview
|
|
@@ -59,7 +59,7 @@ Public marketing, docs, and blog routes render through a swappable public-conten
|
|
|
59
59
|
The public content seam lives under `src/lib/content`.
|
|
60
60
|
|
|
61
61
|
The default built-in adapter is `MinuteWorkPublicSiteContentAdapter`. It calls the
|
|
62
|
-
|
|
62
|
+
PandaWork gateway with a server-only content token and reads the narrow
|
|
63
63
|
`mw.core.site` public-site snapshot contract.
|
|
64
64
|
|
|
65
65
|
`mw.core.site` is treated as a runtime baseline capability. This starter
|
|
@@ -91,13 +91,13 @@ When disabled:
|
|
|
91
91
|
|
|
92
92
|
Copy `.env.example` to `.env.local` when running the template directly. The
|
|
93
93
|
example file uses `MW_PUBLIC_CONTENT_SOURCE=none` so the private `/app` surface
|
|
94
|
-
can boot without
|
|
94
|
+
can boot without PandaWork CMS credentials; set `MW_PUBLIC_CONTENT_SOURCE` to
|
|
95
95
|
`minutework_cms` and fill the CMS values below when enabling the public site.
|
|
96
96
|
|
|
97
97
|
- `MW_PLATFORM_BASE_URL` is required
|
|
98
98
|
- `MW_PUBLIC_CONTENT_SOURCE` defaults to `none` when omitted; supported values are `minutework_cms`, `custom`, `static_json`, and `none`
|
|
99
99
|
- `MW_CONTENT_API_TOKEN` is required only for `minutework_cms` and must stay server-only
|
|
100
|
-
- `MW_TEMPLATE_APP_NAME` defaults to `
|
|
100
|
+
- `MW_TEMPLATE_APP_NAME` defaults to `PandaWork Combined Starter`
|
|
101
101
|
- `MW_PUBLIC_BASE_URL` is required for public content sources and should match the deployed public origin; it may be omitted when `MW_PUBLIC_CONTENT_SOURCE=none`
|
|
102
102
|
- `MW_PUBLIC_SITE_PROPERTY_KEY` is required only for `minutework_cms` and selects the `PublishedWebProperty` backing the site
|
|
103
103
|
- `MW_PUBLIC_SITE_ENV` defaults to `preview`
|
|
@@ -25,7 +25,7 @@ vi.mock("@/lib/platform/endpoints.server", () => ({
|
|
|
25
25
|
|
|
26
26
|
vi.mock("@/lib/platform/env.server", () => ({
|
|
27
27
|
env: {
|
|
28
|
-
MW_TEMPLATE_APP_NAME: "
|
|
28
|
+
MW_TEMPLATE_APP_NAME: "PandaWork Combined Starter",
|
|
29
29
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: false,
|
|
30
30
|
},
|
|
31
31
|
}));
|
|
@@ -47,7 +47,7 @@ describe("runtime commands example page", () => {
|
|
|
47
47
|
it("loads the private shell when the example is enabled", async () => {
|
|
48
48
|
vi.doMock("@/lib/platform/env.server", () => ({
|
|
49
49
|
env: {
|
|
50
|
-
MW_TEMPLATE_APP_NAME: "
|
|
50
|
+
MW_TEMPLATE_APP_NAME: "PandaWork Combined Starter",
|
|
51
51
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: true,
|
|
52
52
|
},
|
|
53
53
|
}));
|
|
@@ -18,7 +18,7 @@ vi.mock("@/lib/platform/endpoints.server", () => ({
|
|
|
18
18
|
|
|
19
19
|
vi.mock("@/lib/platform/env.server", () => ({
|
|
20
20
|
env: {
|
|
21
|
-
MW_TEMPLATE_APP_NAME: "
|
|
21
|
+
MW_TEMPLATE_APP_NAME: "PandaWork Combined Starter",
|
|
22
22
|
MW_ENABLE_RUNTIME_COMMAND_EXAMPLE: false,
|
|
23
23
|
},
|
|
24
24
|
}));
|
|
@@ -6,7 +6,7 @@ import { env } from "@/lib/platform/env.server";
|
|
|
6
6
|
export const metadata = {
|
|
7
7
|
title: "Workspace",
|
|
8
8
|
description:
|
|
9
|
-
"Authenticated workspace surface for the combined
|
|
9
|
+
"Authenticated workspace surface for the combined PandaWork starter.",
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export default async function AppHomePage() {
|