@mindstudio-ai/remy 0.1.257 → 0.1.258

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.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: Scheduled Jobs
3
+ what: Methods that run on a schedule, declared as cron expressions in an interface config and synced to the platform on deploy. Nothing to host and no scheduler to run — a job is a method plus a schedule line.
4
+ when: Before adding a `cron` interface or writing a method meant to run on a timer.
5
+ ---
6
+
7
+ # Cron Interfaces
8
+
9
+ Scheduled method execution.
10
+
11
+ ## Config (`interface.json`)
12
+
13
+ The top-level key must match the interface type (`cron`):
14
+
15
+ ```json
16
+ {
17
+ "cron": {
18
+ "jobs": [
19
+ {
20
+ "schedule": "0 9 * * 5",
21
+ "method": "process-weekly-payments",
22
+ "description": "Process approved invoices every Friday at 9am"
23
+ },
24
+ {
25
+ "schedule": "*/30 * * * *",
26
+ "method": "sync-vendor-status",
27
+ "description": "Sync vendor statuses every 30 minutes"
28
+ }
29
+ ]
30
+ }
31
+ }
32
+ ```
33
+
34
+ Standard cron expression format. `method` is the id of a method in `methods[]`. Jobs are synced to the
35
+ platform on deploy.
36
+
37
+ Declare it in `mindstudio.json`:
38
+
39
+ ```json
40
+ { "type": "cron", "path": "dist/interfaces/cron/interface.json" }
41
+ ```
42
+
43
+ ## Auth
44
+
45
+ Methods invoked through this interface run with `auth.roles: ['system']` — the platform is calling, not
46
+ a user session, so there's no user to impersonate. Use `auth.requireRole('system')` to gate methods that
47
+ should only be reachable on a schedule. The auth reference in your system prompt covers the system role
48
+ in full.
49
+
50
+ A scheduled job that needs to act on user data acts as the system, not as any user, so it reaches
51
+ everything. Scope what it touches in the method itself rather than relying on role checks to narrow it.
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: Webhooks
3
+ what: Inbound HTTP endpoints that run a method synchronously, routed by a secret in the URL rather than by an auth header — which is what makes them the right fit for provider callbacks from Stripe, GitHub, Shopify, Slack or Twilio, since those senders can't present a bearer token. Signature verification works natively off the raw request body.
4
+ when: Before adding a `webhook` interface or writing a method that receives a provider callback. Also load it before reaching for any confirmation-token, polling, or proxy workaround for inbound HTTP — those aren't needed here.
5
+ ---
6
+
7
+ # Webhook Interfaces
8
+
9
+ Inbound HTTP endpoints that invoke a method directly and synchronously — the caller waits for the
10
+ method to finish. Use for receiving webhooks from external services (Stripe, GitHub, Shopify, Slack,
11
+ Twilio). Direct inbound webhooks with signature verification work natively; do **not** build
12
+ confirmation-token or polling workarounds.
13
+
14
+ The other native path for inbound HTTP is the API interface, which uses bearer auth and exposes the raw
15
+ body at `input._request.rawBody` instead of at the top level. Use that one when the caller can send an
16
+ `Authorization` header and you want a documented REST surface; use this one for provider callbacks.
17
+ Load the `restApi` skill if that's the direction.
18
+
19
+ Webhook secrets are configured at the project level by the user through the Remy platform. Your job is
20
+ the `interface.json` and the handling method.
21
+
22
+ ## Config (`interface.json`)
23
+
24
+ The top-level key must match the interface type (`webhook`):
25
+
26
+ ```json
27
+ {
28
+ "webhook": {
29
+ "endpoints": [
30
+ {
31
+ "method": "handle-payment-webhook",
32
+ "secret": "whsec_pick_a_long_random_token",
33
+ "description": "Stripe events"
34
+ }
35
+ ]
36
+ }
37
+ }
38
+ ```
39
+
40
+ - `method` — the id of a method in `methods[]` to invoke.
41
+ - `secret` — a developer-chosen opaque token that is **both the routing key and the access guard**. It
42
+ is stable across deploys (compilation is a passthrough — redeploying never rotates it), so a URL you
43
+ register with Stripe/GitHub stays valid. Generate one long random value per endpoint and keep it
44
+ constant.
45
+ - Declare multiple endpoints if needed; each `secret` maps to one method.
46
+
47
+ Declare it in `mindstudio.json`:
48
+
49
+ ```json
50
+ { "type": "webhook", "path": "dist/interfaces/webhook/interface.json" }
51
+ ```
52
+
53
+ ## Endpoint URL
54
+
55
+ Register this with the external service:
56
+
57
+ ```
58
+ https://{app-host}/_/webhook/{secret}
59
+ ```
60
+
61
+ `{app-host}` is any host the app is served on: its `custom_subdomain` host (e.g.
62
+ `myapp.madewithremy.com`), a custom domain if configured, or the UUID host
63
+ (`<appId>.madewithremy.com` / `.msagent.ai`). All HTTP verbs are accepted.
64
+
65
+ ## Input
66
+
67
+ The method receives:
68
+
69
+ ```ts
70
+ {
71
+ method: string; // HTTP method
72
+ headers: Record<string, string>; // request headers
73
+ query: Record<string, string>; // query params
74
+ body: any; // parsed JSON / form body
75
+ rawBody: string; // exact raw request bytes (UTF-8), pre-parse
76
+ }
77
+ ```
78
+
79
+ For signature verification **always use `rawBody`, never `body`** — providers (Stripe, GitHub, Shopify,
80
+ Slack) HMAC the raw payload, and a re-serialized `body` will not match:
81
+
82
+ ```typescript
83
+ const event = stripe.webhooks.constructEvent(
84
+ input.rawBody,
85
+ input.headers['stripe-signature'],
86
+ process.env.STRIPE_WEBHOOK_SECRET!,
87
+ );
88
+ ```
89
+
90
+ `rawBody` is populated for `application/json` and `application/x-www-form-urlencoded` bodies (what these
91
+ providers send).
92
+
93
+ ## Response
94
+
95
+ Whatever the method returns as output is sent back to the caller as JSON; if it returns no output, the
96
+ platform responds `204`. A wrong/unknown secret returns `401`; an app with no live release returns
97
+ `404`.
98
+
99
+ ## Auth
100
+
101
+ Methods invoked through this interface run with `auth.roles: ['system']` — the platform is calling, not
102
+ a user session, so there's no user to impersonate. Use `auth.requireRole('system')` to gate methods that
103
+ should only be reachable via a platform trigger. The auth reference in your system prompt covers the
104
+ system role in full.
105
+
106
+ Note that the URL secret is the only access control on the endpoint itself, which is why it needs to be
107
+ long and random. Signature verification is a second, independent check that the payload really came from
108
+ the provider — do both.
@@ -19,7 +19,7 @@ The scaffold starts with these spec files that cover the full picture of the app
19
19
  - **`src/interfaces/@brand/voice.md`** — voice and terminology: tone, error messages, word choices
20
20
  - **`src/roadmap/`** — feature roadmap. One file per feature (`type: roadmap`). See "Roadmap" below.
21
21
 
22
- These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `agent.md`, etc.) if the app uses them. For external HTTP, the Webhook interface (`webhook.md`) handles inbound provider webhooks (Stripe, GitHub) via secret-in-URL routing, while the API interface (`api.md`) covers bearer-auth sync endpoints, public REST APIs, and batch tools. Organize however serves clarity — the platform reads the entire `src/` folder.
22
+ These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `email.md`, `mcp.md`, `agent.md`) if the app uses them. Each of those has a skill carrying its spec format and config — `restApi`, `webhooks`, `scheduledJobs`, `inboundEmail`, `mcpInterfaces`, `agentInterfaces` — and you should load the relevant one before writing the spec rather than after, since the spec is what the config is compiled from. For external HTTP the choice is between two of them: the Webhook interface handles inbound provider webhooks (Stripe, GitHub) via secret-in-URL routing, while the API interface covers bearer-auth sync endpoints, public REST APIs, and batch tools. Organize however serves clarity — the platform reads the entire `src/` folder.
23
23
 
24
24
  Remember: users care about look and feel as much as (and often more than) underlying data structures. Don't treat the brand and interface specs as an afterthought — for many users, the visual identity and voice are the first things they want to get right.
25
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.257",
3
+ "version": "0.1.258",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",