@everystack/mcp 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +37 -10
  2. package/dist/adding-database.md +169 -0
  3. package/dist/admin.md +81 -0
  4. package/dist/auth.md +115 -0
  5. package/dist/aws-setup.md +276 -0
  6. package/dist/cli.md +108 -0
  7. package/dist/client-api.md +145 -0
  8. package/dist/core.md +196 -0
  9. package/dist/deployment.md +146 -0
  10. package/dist/events.md +87 -0
  11. package/dist/first-run.md +100 -0
  12. package/dist/getting-started.md +75 -0
  13. package/dist/handler-options.md +114 -0
  14. package/dist/images.md +93 -0
  15. package/dist/index.cjs +23726 -0
  16. package/dist/jobs.md +97 -0
  17. package/dist/logging.md +91 -0
  18. package/dist/plugins.md +68 -0
  19. package/dist/project-claude-md.md +102 -0
  20. package/dist/query-protocol.md +129 -0
  21. package/dist/schema-patterns.md +167 -0
  22. package/dist/security-device.md +99 -0
  23. package/dist/security.md +270 -0
  24. package/dist/ssr.md +82 -0
  25. package/dist/storage.md +63 -0
  26. package/dist/testing.md +118 -0
  27. package/package.json +11 -9
  28. package/src/gates/detectors/embedded-data-bundle.ts +58 -0
  29. package/src/gates/detectors/hand-written-migration.ts +42 -0
  30. package/src/gates/detectors/secret-in-public-env.ts +41 -0
  31. package/src/gates/engine.ts +80 -0
  32. package/src/gates/registry.ts +25 -0
  33. package/src/gates/telemetry.ts +143 -0
  34. package/src/gates/types.ts +70 -0
  35. package/src/governance/cli.ts +193 -0
  36. package/src/governance/grounding.ts +344 -0
  37. package/src/index.ts +97 -50
  38. package/src/prompts/claude-md.ts +90 -0
  39. package/src/prompts/governance-setup.ts +85 -0
  40. package/src/prompts/index.ts +4 -0
  41. package/src/prompts/new-app.ts +4 -1
  42. package/src/resources/project-claude-md.md +69 -94
  43. package/src/tools/index.ts +6 -39
@@ -0,0 +1,114 @@
1
+ # Handler Options Reference
2
+
3
+ > Complete reference for `createHandler(db, schema, options)` from `@everystack/api/handler`.
4
+
5
+ ## When to Use
6
+ Read this when configuring the PostgREST handler for a V2+ app. Every option is optional -- start minimal and add as needed.
7
+
8
+ ## Setup
9
+
10
+ ```typescript
11
+ import { createHandler } from '@everystack/api/handler';
12
+ import * as schema from '../db/schema';
13
+
14
+ const handler = createHandler(db, schema, {
15
+ basePath: '/api', // Strip this prefix from incoming URLs
16
+ // ... options below
17
+ });
18
+ ```
19
+
20
+ Returns `(request: Request) => Promise<Response>`.
21
+
22
+ ## Options
23
+
24
+ ### auth
25
+ ```typescript
26
+ auth: {
27
+ verifyToken: async (token: string) => payload | null, // Required for auth
28
+ publicRoutes: ['GET'], // Methods that skip token verification
29
+ publicRpc: ['health'], // RPC functions that skip all auth (token + client)
30
+ roleHierarchy: ['public', 'authenticated', 'admin'], // For RPC role gates
31
+ roleField: 'role', // JWT field containing user's role
32
+ onAuthenticated: (user) => {}, // Callback after successful auth
33
+ // Client credentials (two-tier auth)
34
+ verifyClient: async (clientId, clientSecret, referer?) => client | null,
35
+ clientHeaders: { id: 'X-Client-Id', secret: 'X-Client-Secret' },
36
+ onClientAuthenticated: (client) => {},
37
+ }
38
+ ```
39
+
40
+ ### pgSettings (RLS)
41
+ ```typescript
42
+ pgSettings: (user, client) => ({
43
+ role: user?.role === 'admin' ? 'admin' : user ? 'authenticated' : 'anon',
44
+ 'request.jwt.claims': JSON.stringify(user || { role: 'anon' }),
45
+ 'app.user_id': String(user?.sub || ''),
46
+ })
47
+ ```
48
+ The `role` key triggers `SET LOCAL ROLE`. All other keys use `set_config(key, value, true)`. Everything is LOCAL scope (resets when transaction ends).
49
+
50
+ ### relations
51
+ ```typescript
52
+ relations: {
53
+ posts: {
54
+ author: { table: 'users', from: 'authorId', to: 'id' }, // many-to-one
55
+ comments: { table: 'comments', from: 'id', to: 'postId', many: true }, // one-to-many
56
+ },
57
+ }
58
+ ```
59
+ Enables `?select=*,author(*)` embedding. Resolved via batched `WHERE IN` (no N+1).
60
+
61
+ ### rpc
62
+ ```typescript
63
+ rpc: {
64
+ health: async (body) => ({ status: 'ok' }), // Function syntax
65
+ timeline: { fn: async (body, user) => {}, role: 'authenticated' }, // Object + role
66
+ admin_stats: { fn: async (body, user) => {}, role: 'admin' },
67
+ }
68
+ ```
69
+ Function syntax uses publicRpc/publicRoutes rules. Object syntax enforces role requirement.
70
+
71
+ ### hooks
72
+ ```typescript
73
+ hooks: {
74
+ posts: {
75
+ beforeCreate: async (body, user, client) => ({ ...body, authorId: user?.sub }),
76
+ afterCreate: async (row, user, client) => {},
77
+ beforeUpdate: async (body, user, client) => body,
78
+ afterUpdate: async (rows, user, client) => {},
79
+ beforeDelete: async (user, client) => {},
80
+ afterDelete: async (rows, user, client) => {},
81
+ },
82
+ }
83
+ ```
84
+ `beforeCreate`/`beforeUpdate` can modify the body by returning a new object.
85
+
86
+ ### Access Control
87
+ ```typescript
88
+ exposedTables: ['posts', 'profiles'], // 404 for unlisted tables
89
+ hiddenColumns: { users: ['passwordHash'] }, // Strip from all responses
90
+ protectedFields: { profiles: ['role'] }, // Strip from incoming writes
91
+ rowOwnership: { posts: { column: 'authorId', userField: 'sub' } }, // Scope writes to owner
92
+ ```
93
+
94
+ ### Safety Limits
95
+ ```typescript
96
+ maxEmbedDepth: 3, // Max relation nesting depth (default: 3)
97
+ maxLimit: 1000, // Max ?limit= value (default: 10000)
98
+ ```
99
+
100
+ ### Other
101
+ ```typescript
102
+ softDelete: { column: 'deletedAt', tables: ['posts'] }, // DELETE -> UPDATE SET deletedAt
103
+ naming: 'snake_case', // Response key format ('camelCase' default)
104
+ ```
105
+
106
+ ## Gotchas
107
+
108
+ - `pgSettings` wraps every query in a transaction. Without it, queries execute directly (no RLS).
109
+ - `hiddenColumns` strips AFTER query execution. Columns are still in the SQL result, just removed from JSON.
110
+ - `protectedFields` strips BEFORE hooks run. Hooks never see protected fields.
111
+ - `exposedTables` doesn't affect RPC endpoints.
112
+ - `rowOwnership` only affects PATCH and DELETE. Reads are governed by RLS.
113
+ - The `role` value in pgSettings is validated against `^[a-zA-Z_][a-zA-Z0-9_]*$`.
114
+ - DELETE without filters returns 400 (safety). Always include at least one filter.
package/dist/images.md ADDED
@@ -0,0 +1,93 @@
1
+ # Image Processing
2
+
3
+ > On-demand Sharp image processing on Lambda. Import from `@everystack/images`.
4
+
5
+ ## When to Use
6
+ Read this when adding image resizing, format conversion, or variant generation (V3).
7
+
8
+ ## Setup
9
+
10
+ ```typescript
11
+ // server/image.ts
12
+ import { createImageHandler } from '@everystack/server/image';
13
+
14
+ export const handler = createImageHandler({
15
+ bucket: Resource.Media.name,
16
+ pathPrefix: '/media/',
17
+ });
18
+ ```
19
+
20
+ ## URL-based Processing
21
+
22
+ Images are processed on-the-fly via query parameters:
23
+
24
+ ```
25
+ /media/photo.jpg?w=400&h=300&fit=cover&fm=webp&q=80
26
+ ```
27
+
28
+ | Parameter | Description | Values |
29
+ |-----------|-------------|--------|
30
+ | `w` | Width | pixels |
31
+ | `h` | Height | pixels |
32
+ | `fit` | Resize mode | `cover`, `contain`, `fill`, `inside`, `outside` |
33
+ | `fm` | Output format | `webp`, `avif`, `jpeg`, `png` |
34
+ | `q` | Quality | 1-100 |
35
+
36
+ ## Variant Generation
37
+
38
+ Pre-generate variants via background jobs:
39
+
40
+ ```typescript
41
+ import { generateVariants } from '@everystack/images/jobs';
42
+
43
+ await publishJob('image:process', {
44
+ key: 'uploads/photo.jpg',
45
+ variants: [
46
+ { name: 'thumb', width: 150, height: 150, fit: 'cover' },
47
+ { name: 'large', width: 1200, format: 'webp', quality: 85 },
48
+ ],
49
+ });
50
+ ```
51
+
52
+ ## EXIF Extraction
53
+
54
+ ```typescript
55
+ import { extractExif } from '@everystack/images';
56
+
57
+ const exif = await extractExif(buffer);
58
+ // { width, height, orientation, gps, camera, ... }
59
+ ```
60
+
61
+ ## Schema
62
+
63
+ ```typescript
64
+ import { imagesSchema } from '@everystack/images/schema';
65
+ // Adds: image_variants table tracking generated variants
66
+ ```
67
+
68
+ ## S3 Origin Cache
69
+
70
+ CloudFront caches are per-region. Enable `s3Cache` to persist rendered images to S3 so the first Sharp render is the last, globally:
71
+
72
+ ```typescript
73
+ export const handler = createImageHandler({
74
+ bucket: Resource.Media.name,
75
+ s3Cache: { enabled: true },
76
+ });
77
+ ```
78
+
79
+ Cache keys are deterministic from parsed params. Add a 30-day lifecycle rule on the `cache/` prefix to auto-expire stale renders. To clean up immediately when an original is deleted:
80
+
81
+ ```typescript
82
+ import { deleteImageCache } from '@everystack/server/image';
83
+ await deleteImageCache(bucket, 'uploads/photo.jpg');
84
+ ```
85
+
86
+ See `docs/caching.md` for full setup.
87
+
88
+ ## Gotchas
89
+
90
+ - Sharp runs on Lambda ARM64 (uses Lambda layer or bundled binary)
91
+ - First request for a variant is slow (processing), subsequent are cached by CloudFront and S3
92
+ - With `s3Cache` enabled, Sharp runs once per variant globally (not once per CloudFront region)
93
+ - AVIF encoding is slower than WebP but produces smaller files