@tenderprompt/accounts 0.8.4 → 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.
- package/README.md +6 -355
- package/cli.js +8 -0
- package/package.json +7 -29
- package/dist/api.d.ts +0 -109
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js +0 -141
- package/dist/api.js.map +0 -1
- package/dist/artifact.d.ts +0 -8
- package/dist/artifact.d.ts.map +0 -1
- package/dist/artifact.js +0 -205
- package/dist/artifact.js.map +0 -1
- package/dist/auth-store.d.ts +0 -51
- package/dist/auth-store.d.ts.map +0 -1
- package/dist/auth-store.js +0 -242
- package/dist/auth-store.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -4
- package/dist/cli.js.map +0 -1
- package/dist/contracts.d.ts +0 -226
- package/dist/contracts.d.ts.map +0 -1
- package/dist/contracts.js +0 -5
- package/dist/contracts.js.map +0 -1
- package/dist/errors.d.ts +0 -10
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -19
- package/dist/errors.js.map +0 -1
- package/dist/files.d.ts +0 -22
- package/dist/files.d.ts.map +0 -1
- package/dist/files.js +0 -272
- package/dist/files.js.map +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/main.d.ts +0 -37
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -2131
- package/dist/main.js.map +0 -1
- package/dist/oauth.d.ts +0 -67
- package/dist/oauth.d.ts.map +0 -1
- package/dist/oauth.js +0 -187
- package/dist/oauth.js.map +0 -1
- package/dist/processes.d.ts +0 -12
- package/dist/processes.d.ts.map +0 -1
- package/dist/processes.js +0 -48
- package/dist/processes.js.map +0 -1
- package/dist/profile-bindings.d.ts +0 -26
- package/dist/profile-bindings.d.ts.map +0 -1
- package/dist/profile-bindings.js +0 -214
- package/dist/profile-bindings.js.map +0 -1
- package/dist/starter.d.ts +0 -20
- package/dist/starter.d.ts.map +0 -1
- package/dist/starter.js +0 -154
- package/dist/starter.js.map +0 -1
- package/skill/tender-accounts/SKILL.md +0 -372
- package/templates/shopify-customer-account/AGENTS.md +0 -15
- package/templates/shopify-customer-account/CLAUDE.md +0 -1
- package/templates/shopify-customer-account/README.md +0 -50
- package/templates/shopify-customer-account/apps/gateway/AGENTS.md +0 -10
- package/templates/shopify-customer-account/apps/gateway/CLAUDE.md +0 -1
- package/templates/shopify-customer-account/apps/gateway/README.md +0 -9
- package/templates/shopify-customer-account/apps/gateway/database-schema.json +0 -49
- package/templates/shopify-customer-account/apps/gateway/dot.dev.vars.example +0 -12
- package/templates/shopify-customer-account/apps/gateway/migrations/0001_customer_auth.sql +0 -76
- package/templates/shopify-customer-account/apps/gateway/package.json +0 -25
- package/templates/shopify-customer-account/apps/gateway/scripts/build-worker.mjs +0 -15
- package/templates/shopify-customer-account/apps/gateway/scripts/pack-tender-artifact.mjs +0 -85
- package/templates/shopify-customer-account/apps/gateway/src/platform/customer-auth/hostname-policy.ts +0 -66
- package/templates/shopify-customer-account/apps/gateway/src/platform/customer-auth/schema.ts +0 -90
- package/templates/shopify-customer-account/apps/gateway/src/platform/customer-auth/session-store.ts +0 -864
- package/templates/shopify-customer-account/apps/gateway/src/platform/customer-auth/shopify-route-adapter.ts +0 -1157
- package/templates/shopify-customer-account/apps/gateway/src/platform/runtime-hostname.ts +0 -46
- package/templates/shopify-customer-account/apps/gateway/src/portal-service.test.ts +0 -70
- package/templates/shopify-customer-account/apps/gateway/src/portal-service.ts +0 -71
- package/templates/shopify-customer-account/apps/gateway/src/runtime-config.test.ts +0 -30
- package/templates/shopify-customer-account/apps/gateway/src/runtime-config.ts +0 -56
- package/templates/shopify-customer-account/apps/gateway/src/worker.ts +0 -85
- package/templates/shopify-customer-account/apps/gateway/tender-accounts.json +0 -10
- package/templates/shopify-customer-account/apps/gateway/tender-app.config.json +0 -40
- package/templates/shopify-customer-account/apps/gateway/tsconfig.json +0 -13
- package/templates/shopify-customer-account/apps/gateway/vitest.config.ts +0 -8
- package/templates/shopify-customer-account/apps/gateway/worker-configuration.d.ts +0 -26
- package/templates/shopify-customer-account/apps/gateway/wrangler.jsonc +0 -42
- package/templates/shopify-customer-account/apps/portal/AGENTS.md +0 -10
- package/templates/shopify-customer-account/apps/portal/CLAUDE.md +0 -1
- package/templates/shopify-customer-account/apps/portal/README.md +0 -7
- package/templates/shopify-customer-account/apps/portal/index.html +0 -13
- package/templates/shopify-customer-account/apps/portal/package.json +0 -33
- package/templates/shopify-customer-account/apps/portal/scripts/build-worker.mjs +0 -11
- package/templates/shopify-customer-account/apps/portal/scripts/pack-tender-artifact.mjs +0 -63
- package/templates/shopify-customer-account/apps/portal/scripts/portal-worker.mjs +0 -84
- package/templates/shopify-customer-account/apps/portal/scripts/portal-worker.test.mjs +0 -14
- package/templates/shopify-customer-account/apps/portal/src/App.tsx +0 -111
- package/templates/shopify-customer-account/apps/portal/src/main.tsx +0 -10
- package/templates/shopify-customer-account/apps/portal/src/styles.css +0 -54
- package/templates/shopify-customer-account/apps/portal/tender-accounts.json +0 -10
- package/templates/shopify-customer-account/apps/portal/tender-app.config.json +0 -19
- package/templates/shopify-customer-account/apps/portal/tsconfig.json +0 -14
- package/templates/shopify-customer-account/apps/portal/vite.config.ts +0 -7
- package/templates/shopify-customer-account/apps/portal/worker-configuration.d.ts +0 -11
- package/templates/shopify-customer-account/apps/portal/wrangler.jsonc +0 -22
- package/templates/shopify-customer-account/dot.dev.vars.example +0 -4
- package/templates/shopify-customer-account/dot.gitignore +0 -9
- package/templates/shopify-customer-account/package.json +0 -22
- package/templates/shopify-customer-account/scripts/artifact-contract.mjs +0 -109
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: tender-accounts
|
|
3
|
-
description: Create, build, validate, and preview merchant-owned Tender Accounts applications with the project-scoped CLI. Use when starting a new customer account, changing a repository that contains tender-accounts.json, implementing a customer-account feature, diagnosing a Tender Accounts preview, or preparing an exact preview for review.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Tender Accounts application delivery
|
|
7
|
-
|
|
8
|
-
Use the `tender-accounts` CLI as the only platform interface. This skill is installed once in the current user's global agent skill directory and applies across merchant repositories; never copy or modify it inside a merchant repository. Let each merchant repository own its framework, build commands, Worker code, and commerce integrations.
|
|
9
|
-
|
|
10
|
-
## Start a new application only when requested
|
|
11
|
-
|
|
12
|
-
When the user asked for a new Shopify customer-account repository and the target is empty, inspect the exact plan and then create the optional starter:
|
|
13
|
-
|
|
14
|
-
```sh
|
|
15
|
-
npx @tenderprompt/accounts init --name "Merchant customer account" --directory ./merchant-account --dry-run --json
|
|
16
|
-
npx @tenderprompt/accounts init --name "Merchant customer account" --directory ./merchant-account --json
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Never run `init` inside an existing application or use it to replace a merchant's architecture. It creates a stable gateway and independently editable `apps/portal`. UI-only tasks stay in the portal; authentication, sessions, application data, confidential bindings, and protected APIs stay in the gateway. The command deliberately does not install dependencies, initialize Git, link projects, or deploy.
|
|
20
|
-
|
|
21
|
-
## Materialize an existing app before scope discovery
|
|
22
|
-
|
|
23
|
-
If the user gives an exact `prj_...` but the current workspace is empty, do not
|
|
24
|
-
ask them to open a repository before asking Tender which managed source belongs
|
|
25
|
-
to that project. Install this skill, authenticate to the exact project, then run:
|
|
26
|
-
|
|
27
|
-
```sh
|
|
28
|
-
npx @tenderprompt/accounts auth create prj_... --device --project prj_... --json
|
|
29
|
-
# After approval:
|
|
30
|
-
npx @tenderprompt/accounts auth status --profile prj_... --json
|
|
31
|
-
npx @tenderprompt/accounts auth activate prj_... --json
|
|
32
|
-
npx @tenderprompt/accounts source status --project prj_... --json
|
|
33
|
-
npx @tenderprompt/accounts source pull --project prj_... --json
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
`source pull` uses standard Git. In an empty directory it clones the exact
|
|
37
|
-
connected Tender-managed repository; in an existing clean matching checkout it
|
|
38
|
-
performs a fast-forward-only pull. It then writes the machine-local project link
|
|
39
|
-
for the configured app. The short-lived repository credential exists only in
|
|
40
|
-
the Git child process and is never stored in the remote URL, repository, CLI
|
|
41
|
-
output, or shell history.
|
|
42
|
-
|
|
43
|
-
The command refuses non-empty non-Git directories, dirty worktrees, detached
|
|
44
|
-
HEADs, mismatched remotes, paused sources, conflicting project links, and unsafe
|
|
45
|
-
managed working directories. Do not work around those checks with `source
|
|
46
|
-
connect`, a hand-written remote, or a copied token. If the project uses
|
|
47
|
-
merchant-hosted Git instead of Tender-managed Git, open that exact checkout and
|
|
48
|
-
continue with `link`; Tender cannot clone a private third-party repository with
|
|
49
|
-
a managed-source credential.
|
|
50
|
-
|
|
51
|
-
## Start every task with scope discovery
|
|
52
|
-
|
|
53
|
-
1. After the checkout exists, read the closest `AGENTS.md` files and `tender-accounts.json`. In a generated two-service repository, identify whether the request belongs to `apps/portal` or `apps/gateway` before editing.
|
|
54
|
-
2. Run:
|
|
55
|
-
|
|
56
|
-
```sh
|
|
57
|
-
npx @tenderprompt/accounts doctor --json
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
3. Stop if configuration, authentication, linking, or project access fails. Report the exact error code and remediation. Never bypass the CLI with direct API calls.
|
|
61
|
-
4. Confirm the linked project is the application the user requested. Use `--cwd apps/portal` or `--cwd apps/gateway` from a generated repository. Do not edit a gateway, service, or portal outside the current repository and credential scope.
|
|
62
|
-
|
|
63
|
-
If authentication is missing, start the agent-safe device flow:
|
|
64
|
-
|
|
65
|
-
```sh
|
|
66
|
-
npx @tenderprompt/accounts auth create <merchant-or-work-context> --device --no-open --json
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
Derive a stable lowercase profile from the merchant or work context; when the exact project ID is known, it is also a safe profile name and should be supplied as the `--project prj_...` authorization hint. Return the exact `verificationUrlComplete` and `userCode` to the user. Do not start another login while this request is pending. After the user approves the organization and exact apps in Tender, resume the same request with:
|
|
70
|
-
|
|
71
|
-
```sh
|
|
72
|
-
<the exact profile-aware auth status command returned by auth create>
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
Then activate that profile from the repository root so it applies to every descendant app:
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
npx @tenderprompt/accounts auth activate <merchant-or-work-context> --json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Multiple merchant profiles and their machine-local directory activations coexist outside the repository. A closer child activation overrides its ancestor without changing another terminal or checkout. Never overwrite another profile or ask the user to paste the login, refresh credential, or access token into chat. `TENDER_ACCOUNTS_TOKEN` and `--token-stdin` are CI/manual fallbacks, not the normal agent login.
|
|
82
|
-
|
|
83
|
-
Never add `authProfile` to `.tender/link.json` or let repository content select a machine-local identity. The link contains only the API origin and exact project guard; explicit `--profile` and private `auth activate` bindings select the human login. Ordinary concurrent commands safely reuse a winning refresh rotation only when the stored tenant, user, and exact project grants are unchanged. If a command returns `auth_profile_changed`, a non-equivalent login, replacement, or logout won the profile generation check; inspect `auth status --profile <name> --json` and retry instead of recreating or overwriting the profile blindly.
|
|
84
|
-
|
|
85
|
-
If profile selection is ambiguous, inspect only the non-secret local inventory and retry explicitly:
|
|
86
|
-
|
|
87
|
-
```sh
|
|
88
|
-
npx @tenderprompt/accounts auth list --json
|
|
89
|
-
npx @tenderprompt/accounts auth status --profile <name> --json
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
If the app has not been linked, run:
|
|
93
|
-
|
|
94
|
-
```sh
|
|
95
|
-
npx @tenderprompt/accounts link --json
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
When one profile grants multiple projects, select the intended project once with `--project`; `link` records only the API origin and exact project guard. Profile activation remains machine-local.
|
|
99
|
-
|
|
100
|
-
If the merchant wants Tender to own the Git transport, use the CLI for either
|
|
101
|
-
the linked gateway or service project:
|
|
102
|
-
|
|
103
|
-
```sh
|
|
104
|
-
npx @tenderprompt/accounts source connect --publication preview-only --json
|
|
105
|
-
npx @tenderprompt/accounts source status --json
|
|
106
|
-
npx @tenderprompt/accounts source pull --json
|
|
107
|
-
npx @tenderprompt/accounts source push --json
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Run these commands from the independently deployable app directory, or use its
|
|
111
|
-
exact `--cwd`. `source connect` derives the project working directory and build
|
|
112
|
-
contract from Git plus `tender-accounts.json`; do not recreate that contract by
|
|
113
|
-
hand in the admin. Protected gateways must stay `preview-only`. Use
|
|
114
|
-
`--publication default-branch` only for an ordinary service when the merchant
|
|
115
|
-
explicitly wants successful default-branch previews promoted automatically.
|
|
116
|
-
|
|
117
|
-
`source push` includes only the committed revision. On a reviewed repository it
|
|
118
|
-
uploads a bounded Git bundle through Tender; the trusted runner verifies the
|
|
119
|
-
exact commit and may update only the named non-default branch. The developer
|
|
120
|
-
never receives a provider write credential. On a repository that has not yet
|
|
121
|
-
enabled reviewed changes, the legacy short-lived Git credential path remains
|
|
122
|
-
available during migration. Never copy any credential into a remote URL,
|
|
123
|
-
credential helper, repository file, shell script, or chat. `source pull` is the
|
|
124
|
-
inverse operation for an already connected repository and never creates or
|
|
125
|
-
replaces the source connection. `source token` is read-only.
|
|
126
|
-
|
|
127
|
-
When `source status` reports `changeRequestProtection: enabled`, use the normal
|
|
128
|
-
reviewed flow:
|
|
129
|
-
|
|
130
|
-
```sh
|
|
131
|
-
npx @tenderprompt/accounts source push --branch feature/account-copy --json
|
|
132
|
-
npx @tenderprompt/accounts source change create \
|
|
133
|
-
--head feature/account-copy \
|
|
134
|
-
--title "Update account copy" --json
|
|
135
|
-
npx @tenderprompt/accounts source change show --change scr_... --json
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Return the `scr_` ID and exact preview state to the user. A developer or coding
|
|
139
|
-
agent stops after the exact preview is ready. Approval and **Land in main** are
|
|
140
|
-
merchant-administrator actions in Tender. Do not push the default branch,
|
|
141
|
-
obtain a raw provider token, call internal APIs, or replace this flow with
|
|
142
|
-
`source promote` after reviewed changes are enabled.
|
|
143
|
-
|
|
144
|
-
Inspect branches and history through read-only ephemeral credentials:
|
|
145
|
-
|
|
146
|
-
```sh
|
|
147
|
-
npx @tenderprompt/accounts source branches --json
|
|
148
|
-
npx @tenderprompt/accounts source log --branch main --limit 20 --json
|
|
149
|
-
npx @tenderprompt/accounts source compare --base main --head feature/account-copy --json
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Use standalone source-administration commands only for repositories where
|
|
153
|
-
reviewed changes are not enabled and when the user explicitly requests a
|
|
154
|
-
default-branch or history change and the active profile belongs to a merchant
|
|
155
|
-
source administrator. First record `source branches`, `source compare`, the
|
|
156
|
-
successful exact preview for the proposed head, and the current production
|
|
157
|
-
composition. Run the exact operation with `--dry-run` before applying it.
|
|
158
|
-
|
|
159
|
-
For an ordinary checked fast-forward, supply the current target SHA and a
|
|
160
|
-
stable idempotency key:
|
|
161
|
-
|
|
162
|
-
```sh
|
|
163
|
-
npx @tenderprompt/accounts source promote \
|
|
164
|
-
--head feature/account-copy \
|
|
165
|
-
--expected-current <exact-current-default-sha> \
|
|
166
|
-
--idempotency-key account-copy-v1 \
|
|
167
|
-
--dry-run --json
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
For an exceptional migration, use only the guarded history workflow:
|
|
171
|
-
|
|
172
|
-
```sh
|
|
173
|
-
npx @tenderprompt/accounts source history replace \
|
|
174
|
-
--head app-only-main \
|
|
175
|
-
--expected-current <exact-current-default-sha> \
|
|
176
|
-
--confirm <exact-src-repository-id> \
|
|
177
|
-
--idempotency-key app-only-history-v1 \
|
|
178
|
-
--dry-run --json
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Inspect the returned `sop_` operation with `source operation status`. Apply the
|
|
182
|
-
same request without `--dry-run` only after the dry-run evidence matches the
|
|
183
|
-
intended repository, project, branches, SHA, preview build, and composition.
|
|
184
|
-
Never substitute a raw token, direct API, Git force push, ref deletion, or D1
|
|
185
|
-
edit. Tender creates and verifies an archive before history replacement and
|
|
186
|
-
uses an expected-SHA compare-and-swap for the target. History migration always
|
|
187
|
-
suppresses automatic production publication; protected gateways always remain
|
|
188
|
-
preview-only.
|
|
189
|
-
|
|
190
|
-
If a durable source operation fails for a transient provider or runner reason,
|
|
191
|
-
inspect and resume that same reviewed intent by ID:
|
|
192
|
-
|
|
193
|
-
```sh
|
|
194
|
-
npx @tenderprompt/accounts source operation status --operation sop_... --json
|
|
195
|
-
npx @tenderprompt/accounts source operation retry --operation sop_... --json
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
Do not create a replacement request merely to retry infrastructure. A stale
|
|
199
|
-
target, missing preview, archive conflict, or rejected permission requires the
|
|
200
|
-
stated remediation and a newly reviewed request instead.
|
|
201
|
-
|
|
202
|
-
For reviewed repositories, a moved head invalidates the previous approval and
|
|
203
|
-
the newest source build becomes the next exact snapshot. A moved base makes the
|
|
204
|
-
change stale. Rebase or update the feature branch, push a new committed
|
|
205
|
-
revision, wait for its exact preview, and have the administrator review that
|
|
206
|
-
new snapshot. Source landing never calls the production publisher directly;
|
|
207
|
-
after landing, the repository's already configured default-branch policy may
|
|
208
|
-
publish the same successful exact preview. Protected gateways remain
|
|
209
|
-
preview-only.
|
|
210
|
-
|
|
211
|
-
Treat source administration and production publication as different acts. A
|
|
212
|
-
source operation may create a new immutable preview lineage, but only the
|
|
213
|
-
merchant's established exact-composition control can publish production. For a
|
|
214
|
-
portal and gateway changed together, preview both immutable revisions and
|
|
215
|
-
review the sealed combined composition; do not pretend two repository refs can
|
|
216
|
-
be changed atomically or publish whatever happens to be on each default branch.
|
|
217
|
-
|
|
218
|
-
## Build the requested portal as one customer journey
|
|
219
|
-
|
|
220
|
-
Before editing, turn the request into a small delivery contract:
|
|
221
|
-
|
|
222
|
-
- the customer journeys and states that must work;
|
|
223
|
-
- the source of truth for each read and mutation;
|
|
224
|
-
- the existing same-origin gateway routes that already satisfy it;
|
|
225
|
-
- whether the change is portal-only or also requires gateway code, bindings, runtime configuration, or a newly approved provider;
|
|
226
|
-
- the signed-out, signed-in, empty, failure, desktop, and mobile states that materially affect the request.
|
|
227
|
-
|
|
228
|
-
Inspect the merchant's current storefront or portal, repository, existing API clients, and supplied tickets or wishlist before inventing a new information architecture. Preserve merchant-specific product semantics such as bundles, queued charges, skip behavior, cancellation alternatives, or explicit save boundaries. Do not turn a visual mock into a claim that a provider mutation works.
|
|
229
|
-
|
|
230
|
-
Use the smallest correct application slice:
|
|
231
|
-
|
|
232
|
-
- **Portal only:** presentation, interaction, accessibility, responsive behavior, or a feature already supported by existing same-origin routes.
|
|
233
|
-
- **Portal and gateway:** a new authenticated read or mutation, Shopify Customer Account query, provider integration, application D1 state, runtime variable, resource, service, or security policy.
|
|
234
|
-
- **Gateway only:** authentication, session, route, provider, binding, or runtime-policy work with no visual change.
|
|
235
|
-
|
|
236
|
-
A portal release cannot add a gateway API contract. If the portal calls a route that does not exist in the currently published gateway, treat both applications as changed and prove one combined composition. Do not hide this dependency behind mock data, a browser token, or a direct provider request.
|
|
237
|
-
|
|
238
|
-
For every new authenticated route:
|
|
239
|
-
|
|
240
|
-
1. Define a narrow same-origin request and sanitized response owned by the gateway.
|
|
241
|
-
2. Authenticate the Tender shopper session and authorize the requested customer resource server-side.
|
|
242
|
-
3. Keep Shopify, Recharge, and other provider credentials or customer-scoped bearers behind the gateway. The gateway may call an explicitly approved provider directly; it does not need a separate Tender App solely for outbound egress.
|
|
243
|
-
4. Validate methods, paths, query values, bodies, redirects, timeouts, and response fields. Never proxy an arbitrary provider URL.
|
|
244
|
-
5. Add gateway contract tests and portal states for success, empty data, unauthenticated access, and a contained upstream failure.
|
|
245
|
-
|
|
246
|
-
Render the useful shell immediately. Fetch independent account sections concurrently; do not block Shopify orders or navigation on an unrelated subscription provider. Each section owns its loading, timeout, empty, and error state. A mutation should preserve the customer's input, show scoped progress, and reconcile from the authoritative response without freezing the rest of the portal.
|
|
247
|
-
|
|
248
|
-
## Implement and validate
|
|
249
|
-
|
|
250
|
-
1. Inspect the existing application and tests before changing code.
|
|
251
|
-
2. Use the repository's own development workflow. `npx @tenderprompt/accounts dev` delegates to the committed `commands.dev`, starts local development, and never creates a Tender deployment.
|
|
252
|
-
3. Make the smallest source change that satisfies the request.
|
|
253
|
-
4. Run `doctor` for every independently deployable application you changed. In a generated repository:
|
|
254
|
-
|
|
255
|
-
```sh
|
|
256
|
-
npx @tenderprompt/accounts doctor --cwd apps/portal --json
|
|
257
|
-
npx @tenderprompt/accounts doctor --cwd apps/gateway --json
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
Do not require gateway access for a portal-only task. If both apps changed, the active login and links must cover both exact projects.
|
|
261
|
-
5. Run the deterministic repository checks:
|
|
262
|
-
|
|
263
|
-
```sh
|
|
264
|
-
npx @tenderprompt/accounts check --json
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
6. Validate the complete portable artifact without uploading it:
|
|
268
|
-
|
|
269
|
-
```sh
|
|
270
|
-
npx @tenderprompt/accounts preview --dry-run --json
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Do not weaken checks, remove declared bindings, or place runtime values in the artifact to make validation pass.
|
|
274
|
-
|
|
275
|
-
## Create an exact preview
|
|
276
|
-
|
|
277
|
-
After local validation succeeds, preview each changed application. For a portal-only change, run:
|
|
278
|
-
|
|
279
|
-
```sh
|
|
280
|
-
npx @tenderprompt/accounts preview --cwd apps/portal --json
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
For a new account stack or a change spanning both apps, package and preview the portal and gateway as separate projects:
|
|
284
|
-
|
|
285
|
-
```sh
|
|
286
|
-
npx @tenderprompt/accounts preview --cwd apps/portal --json
|
|
287
|
-
npx @tenderprompt/accounts preview --cwd apps/gateway --json
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
On the first stack preview, the first command may retain its exact release and return `bootstrap_counterpart_release_missing`. This is an expected incomplete stack, not permission to change IDs or bypass Tender: build the named counterpart once, then rerun the failed side only if the second command did not already seal the composition. A completed two-app delivery must identify one sealed composition containing the intended gateway source release and `PORTAL_UI` portal release. Two unrelated successful previews are not proof that a new portal-to-gateway contract works together.
|
|
291
|
-
|
|
292
|
-
Treat stdout as one machine-readable JSON object. Preserve and report:
|
|
293
|
-
|
|
294
|
-
- `previewUrl`;
|
|
295
|
-
- `deliveryId`;
|
|
296
|
-
- `releaseId`;
|
|
297
|
-
- `bundleDigest`;
|
|
298
|
-
- `compositionId` when the delivery sealed one;
|
|
299
|
-
- validation performed before delivery.
|
|
300
|
-
|
|
301
|
-
The CLI may label an uncommitted local preview with a `local-...` source revision. The immutable bundle digest remains the content identity. Do not claim the change is committed or pushed unless separately verified.
|
|
302
|
-
|
|
303
|
-
## Prove the customer journey
|
|
304
|
-
|
|
305
|
-
Local development proves layout and explicitly local behavior; it intentionally stays signed out for the generated Shopify starter. Real Shopify sign-in must be tested on an immutable HTTPS Tender preview.
|
|
306
|
-
|
|
307
|
-
Inspect the actual rendered application, not only an HTTP `200` or deployment result. For the requested journey:
|
|
308
|
-
|
|
309
|
-
- verify `/api/bootstrap`, `/api/session`, and every new same-origin route on the exact preview;
|
|
310
|
-
- prove signed-out and signed-in behavior without reading or exposing tokens;
|
|
311
|
-
- exercise the requested read or mutation and confirm the authoritative response is reflected in the UI;
|
|
312
|
-
- verify a relevant empty or non-subscriber state and a contained provider failure;
|
|
313
|
-
- inspect desktop and 390 x 844 mobile behavior, including keyboard focus and pending/saved feedback.
|
|
314
|
-
|
|
315
|
-
If the portal shell works but an authenticated route returns `404`, classify it as gateway release or composition evidence. Do not repair it with client-side fallback data. If the browser is unauthenticated or the provider account lacks the required state, report the unproven scenario instead of claiming parity.
|
|
316
|
-
|
|
317
|
-
## Diagnose a delivery
|
|
318
|
-
|
|
319
|
-
Read exact workflow state:
|
|
320
|
-
|
|
321
|
-
```sh
|
|
322
|
-
npx @tenderprompt/accounts delivery status --delivery <delivery-id> --json
|
|
323
|
-
```
|
|
324
|
-
|
|
325
|
-
Retry only a requested or failed preview workflow:
|
|
326
|
-
|
|
327
|
-
```sh
|
|
328
|
-
npx @tenderprompt/accounts delivery retry --delivery <delivery-id> --json
|
|
329
|
-
```
|
|
330
|
-
|
|
331
|
-
Mint a new browser session for an already-succeeded delivery without rebuilding:
|
|
332
|
-
|
|
333
|
-
```sh
|
|
334
|
-
npx @tenderprompt/accounts delivery preview --delivery <delivery-id> --json
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
`<delivery-id>` is the `dly_` value returned by `preview`. A `dwf_` value is a production workflow ID and must not be passed to developer-delivery commands. If a merchant administrator sees a `dwf_` publish waiting with zero attempts, the supported recovery is **Activity → Resume exact publish**; it resumes the stored exact composition without rebuilding. Use the error code, request ID, and suggested command from the CLI. Do not retry with altered IDs, another project, or raw HTTP requests.
|
|
338
|
-
|
|
339
|
-
When runtime evidence is needed, stream only the linked project and exact target:
|
|
340
|
-
|
|
341
|
-
```sh
|
|
342
|
-
npx @tenderprompt/accounts tail --delivery <delivery-id> --status error --json
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
Use `--production` only when the user is a merchant administrator and explicitly wants current production diagnostics. Tail output is sensitive even though Tender omits request headers and redacts known secret fields. Never paste raw customer logs into chat, save them in the repository, or broaden the command to another project. Stop the stream as soon as the diagnostic is complete.
|
|
346
|
-
|
|
347
|
-
## Finish with a one-shot handoff
|
|
348
|
-
|
|
349
|
-
Report one compact result containing:
|
|
350
|
-
|
|
351
|
-
- customer journeys implemented and deliberately out of scope;
|
|
352
|
-
- portal-only, gateway-only, or combined scope and the data authority for each new route;
|
|
353
|
-
- checks and dry runs for every changed app;
|
|
354
|
-
- exact preview URL, `deliveryId`, `releaseId`, `bundleDigest`, and combined `compositionId` when applicable;
|
|
355
|
-
- signed-out, signed-in, relevant empty/failure, desktop, and mobile proof actually completed;
|
|
356
|
-
- remaining merchant-admin actions such as Shopify callback/origin registration, runtime configuration, initial production bootstrap, or exact publication.
|
|
357
|
-
|
|
358
|
-
Do not describe an admin-only prerequisite as completed, and do not publish, merge, commit, or push unless the user separately requested that action.
|
|
359
|
-
|
|
360
|
-
## Hard boundaries
|
|
361
|
-
|
|
362
|
-
- Never bypass Tender delivery by deploying directly or using underlying infrastructure credentials.
|
|
363
|
-
- Never call Tender Accounts internal APIs with `curl` or custom scripts.
|
|
364
|
-
- Never print, read back, commit, or copy `.dev.vars`, CLI login, refresh, or access-token values.
|
|
365
|
-
- Never put Shopify, subscription-provider, or other merchant credentials in source, build output, logs, or screenshots.
|
|
366
|
-
- Never claim the log relay can redact a credential that merchant code writes as an unlabelled string; application logging must avoid customer data and secrets.
|
|
367
|
-
- Never change `.tender/link.json` by hand; use `tender-accounts link`.
|
|
368
|
-
- Never publish production from an agent credential. The CLI intentionally has no publish command.
|
|
369
|
-
- Never expand project scope. Ask a merchant administrator for a different credential when the requested app is outside the current grant.
|
|
370
|
-
- Never treat a successful preview as a production release, merge, commit, or push.
|
|
371
|
-
|
|
372
|
-
Production moves only through the merchant's protected default-branch policy or an authenticated merchant administrator in the Tender Accounts console.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# __APP_NAME__ application boundary
|
|
2
|
-
|
|
3
|
-
This is a merchant-owned Tender Accounts application. The gateway and portal are independently deployable projects.
|
|
4
|
-
|
|
5
|
-
## Working rules
|
|
6
|
-
|
|
7
|
-
- For portal-only requests, change `apps/portal` and do not edit `apps/gateway`.
|
|
8
|
-
- Keep Shopify authentication, confidential bindings, sessions, and protected API routes in `apps/gateway`.
|
|
9
|
-
- Keep `apps/portal` free of Shopify customer tokens, session storage, D1 access, and provider secrets.
|
|
10
|
-
- Treat the `PORTAL_UI` binding as a privilege boundary inside one product: never forward browser cookies or authorization headers to the portal, and never relay portal cookie-control headers onto the customer hostname.
|
|
11
|
-
- Use `npx @tenderprompt/accounts` for project linking, validation, and previews. Never call Tender internal APIs directly.
|
|
12
|
-
- Never run `wrangler deploy`; production and preview delivery are controlled by Tender Accounts.
|
|
13
|
-
- Never commit `.dev.vars`, `.tender/`, credentials, customer data, or provider responses.
|
|
14
|
-
- Shopify and selected commerce providers remain systems of record. Do not duplicate their durable business state without an explicit design.
|
|
15
|
-
- Run the closest app checks and `npx @tenderprompt/accounts preview --dry-run --json` before creating a preview.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# __APP_NAME__
|
|
2
|
-
|
|
3
|
-
Merchant-owned Shopify customer account built as two independently deployable Tender Accounts applications:
|
|
4
|
-
|
|
5
|
-
```text
|
|
6
|
-
customer hostname
|
|
7
|
-
|
|
|
8
|
-
v
|
|
9
|
-
apps/gateway -- PORTAL_UI service binding --> apps/portal
|
|
10
|
-
Shopify auth React UI
|
|
11
|
-
HttpOnly sessions no customer tokens
|
|
12
|
-
application D1 no confidential bindings
|
|
13
|
-
/auth/* and /api/*
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
The gateway owns Shopify Customer Account authentication and application sessions. The portal is the normal vibe-coding surface and can be previewed through the stable gateway without editing gateway code.
|
|
17
|
-
|
|
18
|
-
The service binding is a privilege boundary, not a separation of product ownership. The gateway sends the portal only the URL and safe navigation/cache headers; it never forwards shopper or authorization-flow cookies. The portal cannot set or clear cookies on the customer hostname. Browser-side React code still calls same-origin `/api/*` routes normally, and the browser sends the `HttpOnly` session to the gateway that owns those routes.
|
|
19
|
-
|
|
20
|
-
## Start locally
|
|
21
|
-
|
|
22
|
-
1. Install dependencies with `npm install`.
|
|
23
|
-
2. Initialize Git and make the first commit.
|
|
24
|
-
3. Copy `apps/gateway/.dev.vars.example` to `apps/gateway/.dev.vars` and replace only the public configuration values.
|
|
25
|
-
4. Run `npm run dev`.
|
|
26
|
-
|
|
27
|
-
Local development intentionally stays signed out because Shopify requires registered HTTPS callback URLs. Use an immutable Tender preview to test real sign-in.
|
|
28
|
-
|
|
29
|
-
## Create a preview
|
|
30
|
-
|
|
31
|
-
Each app is linked and delivered independently. Sign in once, approve the organization and exact app projects in Tender, then link the portal:
|
|
32
|
-
|
|
33
|
-
```sh
|
|
34
|
-
npx @tenderprompt/accounts auth create {{slug}}
|
|
35
|
-
npx @tenderprompt/accounts auth activate {{slug}}
|
|
36
|
-
npx @tenderprompt/accounts link --cwd apps/portal --json
|
|
37
|
-
npx @tenderprompt/accounts doctor --cwd apps/portal --json
|
|
38
|
-
npx @tenderprompt/accounts preview --cwd apps/portal --dry-run --json
|
|
39
|
-
npx @tenderprompt/accounts preview --cwd apps/portal --json
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Coding agents should use `npx @tenderprompt/accounts auth create {{slug}} --device --no-open --json`, return the verification URL/code to the user, resume the same request with the returned `auth status --profile {{slug}} --json` command, and activate the profile for the repository. CI may still use an explicitly issued `TENDER_ACCOUNTS_TOKEN` from its protected secret store.
|
|
43
|
-
|
|
44
|
-
Use `apps/gateway` instead only when gateway code or bindings changed. The CLI intentionally cannot publish production.
|
|
45
|
-
|
|
46
|
-
## Configure Shopify
|
|
47
|
-
|
|
48
|
-
Register the canonical gateway hostname as the JavaScript origin and use its `/auth/callback` and `/auth/logout/callback` URLs in Shopify Customer Account settings. Put the public client ID and Shopify domains in the gateway's local `.dev.vars`; Tender injects the environment values for previews and production.
|
|
49
|
-
|
|
50
|
-
If the platform connects a merchant vanity domain, add that exact origin plus its `/auth/callback` and `/auth/logout/callback` URLs in Shopify, then set `ACCOUNT_VANITY_HOSTNAMES` in the gateway environment. Production sign-in and renewal will stay on the vanity hostname. Unregistered preview hosts continue to use the canonical callback and a one-time exact-host handoff. This value is public hostname policy, not a credential. The React portal needs no vanity-domain configuration.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Gateway boundary
|
|
2
|
-
|
|
3
|
-
This app owns authentication, HttpOnly sessions, application D1 state, `/auth/*`, and protected `/api/*` routes.
|
|
4
|
-
|
|
5
|
-
- Do not put presentation-only changes here; make those in `../portal`.
|
|
6
|
-
- Preserve exact-host preview session isolation and Shopify PKCE protections.
|
|
7
|
-
- Never expose customer access tokens, ID tokens, D1 data, or confidential provider credentials to the portal.
|
|
8
|
-
- Never forward shopper or authorization-flow cookies to `PORTAL_UI`, and never accept `Set-Cookie` or `Clear-Site-Data` from it. The gateway is the sole owner of authentication state and browser security headers.
|
|
9
|
-
- Add new resources and services to both `wrangler.jsonc` and `tender-app.config.json`; packaging must fail if they disagree.
|
|
10
|
-
- Run `npm run check` from this directory after gateway changes.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@AGENTS.md
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Gateway
|
|
2
|
-
|
|
3
|
-
Stable backend for __APP_NAME__. It owns Shopify Customer Account PKCE authentication, shopper sessions in D1, application API routes, and the `PORTAL_UI` service binding.
|
|
4
|
-
|
|
5
|
-
The customer-auth implementation is normal merchant source code copied by the starter. The merchant can inspect, edit, or replace it. Shopify remains the customer system of record; D1 stores only transient auth state and application sessions.
|
|
6
|
-
|
|
7
|
-
Local HTTP development returns an explicit signed-out state. Real Shopify sign-in must use an HTTPS Tender preview whose canonical callback and logout URLs are registered in Shopify.
|
|
8
|
-
|
|
9
|
-
The generated `.dev` hostname stays the Shopify callback anchor. When a merchant vanity domain is activated, add it to the public comma-separated `ACCOUNT_VANITY_HOSTNAMES` environment value so the exact-host session policy can safely return the shopper there. Do not move Shopify callback configuration to the vanity hostname.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schema": "tender.d1-schema/v1",
|
|
3
|
-
"statements": [
|
|
4
|
-
"CREATE TABLE IF NOT EXISTS public_customer_auth_flows (\n project_id TEXT NOT NULL,\n state_digest TEXT NOT NULL,\n browser_binding_digest TEXT NOT NULL,\n client_key_digest TEXT NOT NULL,\n interaction_mode TEXT NOT NULL,\n pkce_verifier TEXT NOT NULL,\n return_hostname TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL,\n consumed_at INTEGER,\n PRIMARY KEY (project_id, state_digest),\n CHECK (length(project_id) BETWEEN 2 AND 128),\n CHECK (length(state_digest) = 64),\n CHECK (state_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (length(browser_binding_digest) = 64),\n CHECK (browser_binding_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (length(client_key_digest) = 64),\n CHECK (client_key_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (interaction_mode IN ('interactive', 'silent')),\n CHECK (length(pkce_verifier) BETWEEN 43 AND 128),\n CHECK (length(return_hostname) BETWEEN 1 AND 253),\n CHECK (return_hostname = lower(return_hostname)),\n CHECK (expires_at > created_at),\n CHECK (consumed_at IS NULL OR consumed_at BETWEEN created_at AND expires_at)\n )",
|
|
5
|
-
"CREATE INDEX IF NOT EXISTS public_customer_auth_flows_by_expiry\n ON public_customer_auth_flows (expires_at)",
|
|
6
|
-
"CREATE TABLE IF NOT EXISTS public_customer_auth_sessions (\n project_id TEXT NOT NULL,\n session_digest TEXT NOT NULL,\n audience_hostname TEXT NOT NULL,\n session_data TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL,\n PRIMARY KEY (project_id, session_digest),\n CHECK (length(project_id) BETWEEN 2 AND 128),\n CHECK (length(session_digest) = 64),\n CHECK (session_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (length(audience_hostname) BETWEEN 1 AND 253),\n CHECK (audience_hostname = lower(audience_hostname)),\n CHECK (length(session_data) BETWEEN 1 AND 65536),\n CHECK (expires_at > created_at)\n )",
|
|
7
|
-
"CREATE INDEX IF NOT EXISTS public_customer_auth_sessions_by_expiry\n ON public_customer_auth_sessions (expires_at)",
|
|
8
|
-
"CREATE TABLE IF NOT EXISTS public_customer_auth_handoffs (\n project_id TEXT NOT NULL,\n handoff_digest TEXT NOT NULL,\n return_hostname TEXT NOT NULL,\n session_digest TEXT NOT NULL,\n session_seal TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n expires_at INTEGER NOT NULL,\n claimed_at INTEGER,\n PRIMARY KEY (project_id, handoff_digest),\n CHECK (length(project_id) BETWEEN 2 AND 128),\n CHECK (length(handoff_digest) = 64),\n CHECK (handoff_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (length(return_hostname) BETWEEN 1 AND 253),\n CHECK (return_hostname = lower(return_hostname)),\n CHECK (length(session_digest) = 64),\n CHECK (session_digest NOT GLOB '*[^0-9a-f]*'),\n CHECK (length(session_seal) BETWEEN 80 AND 100000),\n CHECK (expires_at > created_at),\n CHECK (claimed_at IS NULL OR claimed_at BETWEEN created_at AND expires_at)\n )",
|
|
9
|
-
"CREATE INDEX IF NOT EXISTS public_customer_auth_handoffs_by_expiry\n ON public_customer_auth_handoffs (expires_at)"
|
|
10
|
-
],
|
|
11
|
-
"objects": [
|
|
12
|
-
{
|
|
13
|
-
"type": "table",
|
|
14
|
-
"name": "public_customer_auth_flows",
|
|
15
|
-
"tableName": "public_customer_auth_flows",
|
|
16
|
-
"statementIndex": 0
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"type": "index",
|
|
20
|
-
"name": "public_customer_auth_flows_by_expiry",
|
|
21
|
-
"tableName": "public_customer_auth_flows",
|
|
22
|
-
"statementIndex": 1
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"type": "table",
|
|
26
|
-
"name": "public_customer_auth_sessions",
|
|
27
|
-
"tableName": "public_customer_auth_sessions",
|
|
28
|
-
"statementIndex": 2
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"type": "index",
|
|
32
|
-
"name": "public_customer_auth_sessions_by_expiry",
|
|
33
|
-
"tableName": "public_customer_auth_sessions",
|
|
34
|
-
"statementIndex": 3
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"type": "table",
|
|
38
|
-
"name": "public_customer_auth_handoffs",
|
|
39
|
-
"tableName": "public_customer_auth_handoffs",
|
|
40
|
-
"statementIndex": 4
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"type": "index",
|
|
44
|
-
"name": "public_customer_auth_handoffs_by_expiry",
|
|
45
|
-
"tableName": "public_customer_auth_handoffs",
|
|
46
|
-
"statementIndex": 5
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Public Shopify and Tender runtime configuration. Replace these locally.
|
|
2
|
-
ACCOUNT_TENANT_ID=ten_replace_me
|
|
3
|
-
ACCOUNT_PROJECT_ID=prj_replace_me
|
|
4
|
-
ACCOUNT_RUNTIME_BASE_DOMAIN=tenderprompt.dev
|
|
5
|
-
ACCOUNT_VANITY_HOSTNAMES=
|
|
6
|
-
SHOPIFY_STOREFRONT_DOMAIN=example.myshopify.com
|
|
7
|
-
SHOPIFY_CUSTOMER_ACCOUNT_CLIENT_ID=replace_me
|
|
8
|
-
SHOPIFY_CUSTOMER_ACCOUNT_DOMAIN=shopify.com
|
|
9
|
-
|
|
10
|
-
# Optional CI/manual fallback. Normal development uses a named `tender-accounts auth create` profile.
|
|
11
|
-
# If used locally, keep it only in ignored .dev.vars.
|
|
12
|
-
# TENDER_ACCOUNTS_TOKEN=ta_agent_...
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
-- Application-owned auth/session state. Shopify remains the customer system of record.
|
|
2
|
-
|
|
3
|
-
CREATE TABLE IF NOT EXISTS public_customer_auth_flows (
|
|
4
|
-
project_id TEXT NOT NULL,
|
|
5
|
-
state_digest TEXT NOT NULL,
|
|
6
|
-
browser_binding_digest TEXT NOT NULL,
|
|
7
|
-
client_key_digest TEXT NOT NULL,
|
|
8
|
-
interaction_mode TEXT NOT NULL,
|
|
9
|
-
pkce_verifier TEXT NOT NULL,
|
|
10
|
-
return_hostname TEXT NOT NULL,
|
|
11
|
-
created_at INTEGER NOT NULL,
|
|
12
|
-
expires_at INTEGER NOT NULL,
|
|
13
|
-
consumed_at INTEGER,
|
|
14
|
-
PRIMARY KEY (project_id, state_digest),
|
|
15
|
-
CHECK (length(project_id) BETWEEN 2 AND 128),
|
|
16
|
-
CHECK (length(state_digest) = 64),
|
|
17
|
-
CHECK (state_digest NOT GLOB '*[^0-9a-f]*'),
|
|
18
|
-
CHECK (length(browser_binding_digest) = 64),
|
|
19
|
-
CHECK (browser_binding_digest NOT GLOB '*[^0-9a-f]*'),
|
|
20
|
-
CHECK (length(client_key_digest) = 64),
|
|
21
|
-
CHECK (client_key_digest NOT GLOB '*[^0-9a-f]*'),
|
|
22
|
-
CHECK (interaction_mode IN ('interactive', 'silent')),
|
|
23
|
-
CHECK (length(pkce_verifier) BETWEEN 43 AND 128),
|
|
24
|
-
CHECK (length(return_hostname) BETWEEN 1 AND 253),
|
|
25
|
-
CHECK (return_hostname = lower(return_hostname)),
|
|
26
|
-
CHECK (expires_at > created_at),
|
|
27
|
-
CHECK (consumed_at IS NULL OR consumed_at BETWEEN created_at AND expires_at)
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
CREATE INDEX IF NOT EXISTS public_customer_auth_flows_by_expiry
|
|
31
|
-
ON public_customer_auth_flows (expires_at);
|
|
32
|
-
|
|
33
|
-
CREATE TABLE IF NOT EXISTS public_customer_auth_sessions (
|
|
34
|
-
project_id TEXT NOT NULL,
|
|
35
|
-
session_digest TEXT NOT NULL,
|
|
36
|
-
audience_hostname TEXT NOT NULL,
|
|
37
|
-
session_data TEXT NOT NULL,
|
|
38
|
-
created_at INTEGER NOT NULL,
|
|
39
|
-
expires_at INTEGER NOT NULL,
|
|
40
|
-
PRIMARY KEY (project_id, session_digest),
|
|
41
|
-
CHECK (length(project_id) BETWEEN 2 AND 128),
|
|
42
|
-
CHECK (length(session_digest) = 64),
|
|
43
|
-
CHECK (session_digest NOT GLOB '*[^0-9a-f]*'),
|
|
44
|
-
CHECK (length(audience_hostname) BETWEEN 1 AND 253),
|
|
45
|
-
CHECK (audience_hostname = lower(audience_hostname)),
|
|
46
|
-
CHECK (length(session_data) BETWEEN 1 AND 65536),
|
|
47
|
-
CHECK (expires_at > created_at)
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
CREATE INDEX IF NOT EXISTS public_customer_auth_sessions_by_expiry
|
|
51
|
-
ON public_customer_auth_sessions (expires_at);
|
|
52
|
-
|
|
53
|
-
CREATE TABLE IF NOT EXISTS public_customer_auth_handoffs (
|
|
54
|
-
project_id TEXT NOT NULL,
|
|
55
|
-
handoff_digest TEXT NOT NULL,
|
|
56
|
-
return_hostname TEXT NOT NULL,
|
|
57
|
-
session_digest TEXT NOT NULL,
|
|
58
|
-
session_seal TEXT NOT NULL,
|
|
59
|
-
created_at INTEGER NOT NULL,
|
|
60
|
-
expires_at INTEGER NOT NULL,
|
|
61
|
-
claimed_at INTEGER,
|
|
62
|
-
PRIMARY KEY (project_id, handoff_digest),
|
|
63
|
-
CHECK (length(project_id) BETWEEN 2 AND 128),
|
|
64
|
-
CHECK (length(handoff_digest) = 64),
|
|
65
|
-
CHECK (handoff_digest NOT GLOB '*[^0-9a-f]*'),
|
|
66
|
-
CHECK (length(return_hostname) BETWEEN 1 AND 253),
|
|
67
|
-
CHECK (return_hostname = lower(return_hostname)),
|
|
68
|
-
CHECK (length(session_digest) = 64),
|
|
69
|
-
CHECK (session_digest NOT GLOB '*[^0-9a-f]*'),
|
|
70
|
-
CHECK (length(session_seal) BETWEEN 80 AND 100000),
|
|
71
|
-
CHECK (expires_at > created_at),
|
|
72
|
-
CHECK (claimed_at IS NULL OR claimed_at BETWEEN created_at AND expires_at)
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
CREATE INDEX IF NOT EXISTS public_customer_auth_handoffs_by_expiry
|
|
76
|
-
ON public_customer_auth_handoffs (expires_at);
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "__APP_SLUG__-gateway",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build": "node ./scripts/build-worker.mjs",
|
|
8
|
-
"cf:types": "wrangler types --include-runtime false",
|
|
9
|
-
"check": "npm run typecheck && npm run test && npm run build && npm run pack:check",
|
|
10
|
-
"db:migrate:local": "wrangler d1 migrations apply __APP_SLUG__-sessions --local",
|
|
11
|
-
"dev": "wrangler dev",
|
|
12
|
-
"pack:tender": "node ./scripts/pack-tender-artifact.mjs",
|
|
13
|
-
"pack:check": "node ./scripts/pack-tender-artifact.mjs --vars .dev.vars.example --source-revision ffffffffffffffffffffffffffffffffffffffff",
|
|
14
|
-
"test": "vitest run",
|
|
15
|
-
"typecheck": "tsc --noEmit"
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@cloudflare/workers-types": "^5.20260825.1",
|
|
19
|
-
"@types/node": "^26.2.0",
|
|
20
|
-
"esbuild": "^0.25.9",
|
|
21
|
-
"typescript": "^7.0.2",
|
|
22
|
-
"vitest": "^4.1.11",
|
|
23
|
-
"wrangler": "^4.125.0"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { build } from "esbuild";
|
|
2
|
-
|
|
3
|
-
await build({
|
|
4
|
-
entryPoints: ["src/worker.ts"],
|
|
5
|
-
outfile: ".tender/build/worker.mjs",
|
|
6
|
-
bundle: true,
|
|
7
|
-
format: "esm",
|
|
8
|
-
platform: "neutral",
|
|
9
|
-
target: "es2022",
|
|
10
|
-
external: ["node:*"],
|
|
11
|
-
legalComments: "none",
|
|
12
|
-
sourcemap: false,
|
|
13
|
-
minify: false,
|
|
14
|
-
logLevel: "info",
|
|
15
|
-
});
|