Blame

0e123c Claude (MCP) 2026-03-13 17:49:46
[mcp] Normalize spaces to underscores
1
This page is part of the **wikibot.io PRD** (Product Requirements Document). See also: [[Design/Platform_Overview]], [[Design/Data_Model]], [[Design/Auth]], [[Design/Implementation_Phases]].
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
2
3
---
4
5
## Infrastructure cost model
6
0926b1 Claude (MCP) 2026-03-15 01:19:33
[mcp] Add superseded banner to Operations
7
> **Superseded.** This page describes AWS infrastructure costs, CI/CD, and operational procedures for wikibot.io. See [[Design/VPS_Architecture]] for the current plan (Debian 12 VM, systemd, rsync backups, $0 hosting cost). The wiki bootstrap template, attachment storage concepts, and Git remote access design carry forward.
8
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
9
Fixed monthly costs regardless of user count:
10
11
Fixed monthly costs by phase (dev environment, 1 AZ):
12
13
| Phase | What's added | New fixed cost | Cumulative |
14
|-------|-------------|---------------|------------|
15
| 0–3 | EFS + VPC + gateway endpoints (DynamoDB, S3) + Route 53 | $0.50 | **~$0.50/mo** |
16
| 4 (pre-launch) | Secrets Manager endpoint (secrets out of env vars), WAF | ~$12-17 | **~$13-18/mo** |
32483d Claude (MCP) 2026-03-14 20:09:24
[mcp] Update Operations: cost model - remove Bedrock/SQS endpoint costs, add note about DynamoDB Streams approach
17
| 5+ (premium) | (no new endpoints — semantic search uses DynamoDB Streams + local MiniLM) | ~$0 | **~$13-18/mo** |
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
18
| When needed | WorkOS custom domain | $99 | +$99/mo |
19
20
Phases 0–3 use Pulumi-managed environment variables for secrets (redeploy to rotate). Secrets Manager is introduced pre-launch when rotation without redeployment and audit trails matter.
21
0a3ce0 Claude (MCP) 2026-03-14 20:15:30
[mcp] Update Operations: prod cost estimate - only Secrets Manager endpoint doubles, no SQS/Bedrock"
22
Production (2 AZs) doubles interface endpoint costs: ~$1/mo (Phases 0–3), ~$26-36/mo (Phase 4+).
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
23
24
Items that are always free or near-zero:
25
- EFS storage: $0.016/GB/mo IA — pennies at low data volume
26
- VPC itself: $0 (subnets, security groups, route tables have no hourly cost)
27
- DynamoDB on-demand: pay per request, negligible at low traffic
28
- Lambda: scales to zero
29
- CloudFront: free tier covers light traffic
30
- WorkOS: free to 1M MAU
31
32
Variable costs scale with usage:
33
34
| Item | Cost | At 1K users | At 10K users |
35
|------|------|------------|-------------|
36
| Lambda | $0.20/1M requests | ~$0.20 | ~$2 |
37
| DynamoDB on-demand | $1.25/1M writes, $0.25/1M reads | ~$1 | ~$5 |
38
| EFS IA storage | $0.016/GB/month | ~$0.03 | ~$0.30 |
39
| CloudFront | Free tier covers 1TB/mo | ~$0 | ~$0 |
6d89cc Claude (MCP) 2026-03-14 20:14:57
[mcp] Update Operations: variable costs table - replace Bedrock with embedding Lambda compute
40
| Bedrock | N/A (eliminated) | $0 | $0 |
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
41
| WorkOS | $0 to 1M MAU | $0 | $0 |
42
f9b67c Claude (MCP) 2026-03-14 20:15:16
[mcp] Update Operations: 'Why it's not zero' paragraph - remove SQS/Bedrock references
43
**Why it's not zero**: EFS requires Lambda to run in a VPC. EFS itself is accessed via mount targets in the VPC (no endpoint needed). But VPC Lambda can't reach other AWS services (DynamoDB, S3) over the public internet — it needs either a NAT Gateway ($32/mo — too expensive) or VPC endpoints. Gateway endpoints (DynamoDB, S3) are free. Interface endpoints (Secrets Manager) cost ~$7/mo/AZ — only needed when Secrets Manager is introduced pre-launch (Phase 4). Bedrock and SQS endpoints were originally planned but have been eliminated by switching to DynamoDB Streams and local MiniLM embeddings.
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
44
f9b67c Claude (MCP) 2026-03-14 20:15:16
[mcp] Update Operations: 'Why it's not zero' paragraph - remove SQS/Bedrock references
45
**Bottom line**: ~$0.50/mo at rest in Phase 0. ~$13-18/mo from Phase 4 (Secrets Manager endpoint + WAF). No further increase for premium features. "Near-zero cost at rest" is accurate.
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
46
47
---
48
49
## Wiki Bootstrap Template
50
51
When a user creates a new wiki, the repo is initialized with a starter page set that teaches Claude how to use the wiki effectively. This is the onboarding experience — the user connects MCP, starts a conversation, and Claude already knows the conventions.
52
53
### Initial pages
54
55
**Home** — Landing page with the wiki's name and purpose (user-provided at creation), links to the guide and any starter pages.
56
57
**Meta/Wiki Usage Guide** — Instructions for the AI assistant:
58
- Available MCP tools and what they do
59
- Session start protocol (read Home first, then check recent changes)
60
- Page conventions: frontmatter schema, WikiLink syntax, page size guidance (~250–800 words)
61
- Commit message format
62
- When to create new pages vs. update existing ones
63
- How to use categories and tags
64
- Gardening responsibilities (orphan detection, stale page review, link maintenance)
65
66
**Meta/Page Template** — A reference page showing the frontmatter schema, section structure, and WikiLink usage. Claude can copy this pattern when creating new pages.
67
68
### Customization
69
70
The bootstrap template is parameterized by:
71
- Wiki name (provided at creation)
72
- Wiki purpose/description (optional, provided at creation)
73
- Category set (default set provided, user can customize later)
74
75
The default category set matches the existing schema (`actor`, `event`, `trend`, `hypothesis`, `variable`, `reference`, `index`) but users can define their own categories for different research domains.
76
77
### Custom template repos (premium)
78
79
Premium users can create a wiki from any public (or authenticated) Git repo URL. The Lambda clones the template repo, strips its git history, and commits the contents as the wiki's initial state. This enables:
80
81
- Shared team templates ("our standard research wiki layout")
82
- Domain-specific starter kits (e.g., a policy analysis template, a technical due diligence template)
83
- Community-contributed templates (a future marketplace opportunity)
84
85
### Implementation
86
87
The default template is stored on EFS (or bundled with the Lambda deployment). On wiki creation, the Lambda copies it to the new repo directory, performs string substitution for wiki name/purpose, and commits as the initial state. For custom templates (premium), the Lambda clones from the provided Git URL instead.
88
89
---
90
91
## Attachment Storage
92
93
Otterwiki stores attachments as regular files in the git repo and serves them directly from the working tree. With EFS, this works the same as on a VPS — no clone overhead, attachments are just files on a mounted filesystem.
94
95
### MVP approach
96
97
Store attachments in the git repo as-is. Tier limits (50MB free, 1GB premium) keep repo sizes manageable. EFS serves files directly with no performance concern.
98
99
### Future optimization: S3-backed attachment serving
100
101
If large attachments become a problem (EFS cost, Git remote clone times), decouple attachment storage from the git repo:
102
103
1. On upload: store the attachment in S3 at a known path (`s3://attachments/{user}/{wiki}/{filename}`), commit only a lightweight reference file to git (similar to Git LFS pointer format)
104
2. On serve: intercept Otterwiki's attachment serving path, resolve the reference, and redirect to S3 (or serve via CloudFront)
105
106
This could be implemented as:
107
- **Otterwiki plugin** that hooks into the attachment upload/serve lifecycle
108
- **Upstream patch** to Otterwiki adding a pluggable storage backend for attachments (local filesystem vs. S3 vs. LFS)
109
- **Lambda middleware** that intercepts attachment routes and serves from S3 before Otterwiki sees the request
110
111
The plugin or upstream patch approach is preferable — it benefits the broader Otterwiki community and keeps our fork minimal.
112
113
---
114
115
## Git Remote Access
116
117
Every wiki's bare repo is directly accessible via Git protocol over HTTPS. This is a core feature, not an afterthought — users should never feel locked in.
118
119
### Hosted Git remote
120
121
```
122
https://sderle.wikibot.io/third-gulf-war.git
123
```
124
125
Authentication: OAuth JWT or MCP bearer token via Git credential helper, or a dedicated Git access token (simpler for CLI usage).
126
127
**Free tier**: read-only. Users can `git clone` and `git pull` their wiki at any time. This is a data portability guarantee — your wiki is always yours.
128
129
**Premium tier**: read/write. Users can `git push` to the hosted remote, enabling workflows like local editing, CI/CD integration, or scripted bulk imports.
130
131
### Implementation
132
133
API Gateway route (`/{user}/{wiki}.git/*`) → Lambda implementing Git smart HTTP protocol (`git-upload-pack` for clone/fetch, `git-receive-pack` for push). The Lambda accesses the same EFS-mounted repo as the wiki handlers.
134
135
This is a well-documented protocol — the Lambda needs to handle the handful of Git smart HTTP endpoints (`/info/refs`, `/git-upload-pack`, `/git-receive-pack`). Libraries like dulwich can serve these without shelling out to git.
136
137
### External Git sync (premium, future)
138
139
Bidirectional sync with an external remote (GitHub, GitLab, etc.). A separate Lambda triggered on schedule (EventBridge) or webhook:
140
141
1. Open wiki repo on EFS
142
2. `git fetch` from configured external remote
143
3. Attempt fast-forward merge (no conflicts → auto-merge)
144
4. Conflicts → flag for human resolution, do not auto-merge
145
5. Push merged state to external remote
146
6. Trigger re-embedding if semantic search enabled
147
148
Credentials for external remotes stored in Secrets Manager (per-wiki secret, auto-rotation support). This is a future feature — the hosted Git remote is the MVP.
149
150
---
151
152
## Platform: AWS Lambda + EFS
153
154
### Why AWS + EFS
155
2fe4fa Claude (MCP) 2026-03-14 20:15:45
[mcp] Update Operations: AWS rationale - mention DynamoDB Streams instead of Bedrock/SQS"
156
EFS (Elastic File System) is AWS's managed NFS service. Lambda mounts EFS volumes directly, eliminating the git-on-S3 clone/push cycle. Git repos live on a persistent filesystem — Lambda reads/writes them in place, just like a VPS. Combined with AWS's managed service catalog (DynamoDB, DynamoDB Streams, CloudFront, ACM) and first-class Pulumi support, this is the strongest fit.
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
157
158
### Key properties
159
160
- **Git repos on EFS work like local disk** — no clone, no push, no S3 sync, no write locks
161
- EFS Infrequent Access: $0.016/GB/month — a 2MB wiki costs ~$0.00003/month at rest
162
- NFS handles concurrent access natively (git's `index.lock` works on NFS)
163
- Lambda scales to zero; EFS cost is storage-only when idle
164
- Built-in backup via AWS Backup (to S3)
165
166
### VPC networking
167
168
EFS requires Lambda to run in a VPC. VPC Lambda can't reach AWS services (DynamoDB, SQS, Bedrock, S3) over the public internet — it needs either a NAT Gateway ($32/mo minimum, kills "zero cost at rest") or VPC endpoints.
169
170
- **Gateway endpoints** (free): DynamoDB, S3 — route traffic through the VPC route table
69d36e Claude (MCP) 2026-03-14 20:15:05
[mcp] Update Operations: VPC networking - SQS/Bedrock endpoints no longer needed
171
- **Interface endpoints** (~$7/mo each per AZ): Secrets Manager — ENI-based, billed hourly + per-GB. SQS and Bedrock endpoints are no longer needed (semantic search uses DynamoDB Streams + local MiniLM embeddings; see [[Design/Async_Embedding_Pipeline]])
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
172
- Minimize AZs in dev (1 AZ = 1× endpoint cost); prod needs 2 AZs for availability
173
174
This is a Phase 0 infrastructure requirement — without endpoints, Lambda can mount EFS but can't reach DynamoDB for ACL checks.
175
176
### Known trade-offs
177
178
- EFS requires a VPC → ~1–2s added to Lambda cold starts (Provisioned Concurrency is available if this proves unacceptable — ~$10-15/mo for 1 warm instance)
179
- EFS latency (~1–5ms per op) is higher than local disk but adequate for git
180
- Mangum adapter needed for Flask on Lambda
181
- API Gateway 29s timeout limits long operations
6b8ebf Claude (MCP) 2026-03-14 20:15:23
[mcp] Update Operations: known trade-offs - VPC endpoint costs reduced (only Secrets Manager)"
182
- VPC interface endpoints add fixed monthly cost (~$7-14/mo in prod for Secrets Manager across 2 AZs)
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
183
184
### S3 fallback
185
186
If Phase 0 testing shows EFS latency or VPC cold starts are unacceptable, fall back to S3-based repos with DynamoDB write locks and clone-to-/tmp. Adds significant complexity (locking, cache management, /tmp eviction) — last resort only.
187
188
### Alternatives considered
189
190
**Fly.io Machines**: Persistent volumes, unmodified Otterwiki, simplest architecture. But weaker IaC, no managed services (embeddings, queues, metadata). Simplest fallback if EFS fails.
191
192
**Google Cloud Run**: Cloud Storage FUSE less proven than EFS for filesystem workloads. No clear advantage over AWS+EFS. Less familiar territory.
193
194
### Phase 0 validates this decision
195
196
Exit criteria: page read <500ms warm, page write <1s warm, cold start <5s total.
197
198
---
199
200
## Infrastructure as Code
201
202
All infrastructure is managed declaratively. No manual console clicking, no snowflake configuration.
203
204
### Tool: Pulumi (Python)
205
206
Pulumi with the Python SDK is the primary IaC tool. Rationale:
207
- Application is Python, so infrastructure code in the same language reduces context switching
208
- Pulumi has first-class AWS support (Lambda, EFS, API Gateway, DynamoDB, ACM, CloudFront, VPC)
209
- Full programming language (loops, conditionals, abstractions) vs. HCL's declarative constraints
210
- Strong secret management built in (`pulumi config set --secret`)
211
212
### What's managed by IaC
213
214
Everything that isn't application code:
215
- Lambda functions (compute, async handlers)
216
- EFS filesystem and mount targets
217
- VPC, subnets, security groups, VPC endpoints (gateway + interface)
218
- API Gateway and CloudFront distributions
219
- WAF web ACLs and rule groups
220
- DynamoDB tables
221
- ACM certificates and Route 53 DNS records
222
- IAM roles and policies
223
- SQS queues
224
- Secrets Manager secrets
225
- EventBridge schedules
226
- CloudWatch monitoring, alerting, and billing alarms
227
- X-Ray tracing configuration
228
- Auth provider configuration (WorkOS AuthKit)
229
- Stripe webhook endpoints
230
231
### What's NOT managed by IaC
232
233
- Application code (deployed via CI/CD pipeline, not Pulumi)
234
- User data (wiki repos, DynamoDB records)
235
- Secrets from external services (Stripe API keys, auth provider secrets) — stored in Pulumi config (`pulumi config set --secret`) and injected as Lambda environment variables during development. Migrated to AWS Secrets Manager pre-launch (Phase 4) for rotation without redeployment and audit trails. The VPC interface endpoint for Secrets Manager is only needed at that point.
236
237
### Repository structure
238
239
```
240
wikibot-io/
241
infra/ # Pulumi project
242
__main__.py # Infrastructure definition
243
config/
244
dev.yaml # Dev stack config
245
prod.yaml # Prod stack config
246
app/ # Application code
247
otterwiki/ # Fork (git submodule or subtree)
248
api/ # REST API handlers
249
mcp/ # MCP server handlers
250
management/ # User/wiki management API
251
frontend/ # SPA
252
deploy/ # CI/CD pipeline definitions
253
```
254
255
---
256
257
## Otterwiki Fork Management
258
259
The Otterwiki fork is kept as minimal as possible. All customizations are either:
260
1. **Plugins** (preferred) — no core changes needed
261
2. **Small, upstreamable patches** — contributed to `schuyler/otterwiki` and submitted as PRs to the upstream `redimp/otterwiki` project
262
3. **Platform-specific overrides** — admin panel section hiding, template conditionals (kept in a separate branch or patch set)
263
264
### Merge strategy
265
266
- Track upstream `redimp/otterwiki` as a remote
267
- Periodically rebase or merge upstream changes into the fork
268
- Keep platform-specific changes isolated (ideally a thin layer on top, not interleaved with upstream code)
269
- Automated CI check: does the fork still pass upstream's test suite after merge?
270
271
### Upstream relationship
272
273
We want to support Otterwiki as a project. Contributions go upstream where possible. If the product generates revenue, donate a portion to the upstream maintainer.
274
275
---
276
277
## Backup and Disaster Recovery
278
279
### What we're protecting
280
281
| Data | Source of truth | Severity of loss |
282
|------|----------------|-----------------|
283
| Git repos (wiki content) | EFS | **Critical** — user data, irreplaceable |
284
| DynamoDB (users, wikis, ACLs) | DynamoDB | **High** — reconstructable from repos but painful |
285
| FAISS indexes | EFS | **Low** — fully rebuildable from repo content |
286
| Auth provider state | WorkOS (external) | **Low** — managed by vendor |
287
288
### Backup strategy
289
290
**Git repos (EFS)**: AWS Backup with daily snapshots, 30-day retention. EFS supports point-in-time recovery via backup. Cost: negligible for small repos.
291
292
**DynamoDB**: Point-in-Time Recovery (PITR) — continuous backups, restore to any second in the last 35 days. Cost: ~$0.20/GB/month (pennies for our data volume).
293
8755ed Claude (MCP) 2026-03-14 20:15:53
[mcp] Update Operations: FAISS recovery cost - no Bedrock cost, just Lambda compute"
294
**FAISS indexes**: No backup needed. Rebuildable from repo content via the embedding Lambda (MiniLM runs locally, no API cost). Loss means a one-time re-embedding of all pages — seconds of Lambda compute per wiki.
832106 Claude (Dev) 2026-03-13 01:54:09
[mcp] Port PRD operations to wiki
295
296
### Recovery scenarios
297
298
| Scenario | Recovery path | RPO | RTO |
299
|----------|--------------|-----|-----|
300
| Single wiki repo corrupted | Restore from EFS backup snapshot | 24h (daily backup) | Minutes |
301
| Bad push overwrites repo | Restore from EFS backup snapshot | 24h | Minutes |
302
| DynamoDB corruption | PITR restore | Seconds | Minutes |
303
| DynamoDB total loss | PITR restore; worst case reconstruct from EFS repo inventory | Seconds | Hours |
304
| FAISS index lost | Re-embed all pages for affected wiki | N/A (rebuildable) | Minutes per wiki |
305
| Full region outage | Accept downtime | N/A | Depends on provider recovery |
306
307
### Design principle
308
309
Git repos are the source of truth. Everything else (DynamoDB records, FAISS indexes) is either backed up with PITR or rebuildable from the repos. A DynamoDB wipe is painful but survivable — you can walk the EFS filesystem and reconstruct user/wiki records from the repo inventory.
310
311
---
312
313
## CI/CD
314
315
Code lives in a private GitHub repo. Deployment via GitHub Actions.
316
317
### Pipeline
318
319
```
320
git push to main
321
→ GitHub Actions:
322
1. Run tests (pytest for Python, vitest/jest for frontend)
323
2. Build artifacts (Lambda zip or container image, SPA bundle)
324
3. Deploy infrastructure changes (pulumi up)
325
4. Deploy Lambda code (zip upload or ECR image push)
326
5. Smoke test (hit health endpoint, create/read/delete a test page)
327
```
328
329
### Environment strategy
330
331
- **dev**: auto-deploy on push to `main`. Separate infrastructure stack (`pulumi stack select dev`). Own domain (`dev.wikibot.io`).
332
- **prod**: manual promotion (GitHub Actions workflow dispatch or tag-based). Separate Pulumi stack. `wikibot.io`.
333
334
---
335
336
## Account Lifecycle
337
338
### Data retention
339
340
User accounts and wiki data are retained indefinitely regardless of activity. Storage cost for an idle wiki is effectively zero (a few KB in DynamoDB, a few MB of git repo on EFS Infrequent Access). There is no reason to delete inactive accounts — it costs nothing to keep them and deleting user data is irreversible.
341
342
### Account deletion
343
344
Users can delete their account from the dashboard. This:
345
1. Deletes all wikis owned by the user (repo, FAISS index, metadata)
346
2. Removes all ACL grants the user has on other wikis
347
3. Deletes the user record from the DynamoDB
348
4. Does NOT delete the auth provider account (Google/GitHub/etc.) — that's the user's own account
349
350
Deletion is permanent and irreversible. Require explicit confirmation ("type your username to confirm").
351
352
### GDPR
353
354
If serving EU users: account deletion satisfies right-to-erasure. Add a data export endpoint (download all wikis as a zip of git repos) to satisfy right-to-portability — though the Git remote access feature already provides this.
355
356
---
357
358
## MCP Discoverability
359
360
MCP tool descriptions must be self-documenting — any MCP-capable client (Claude, GPT, Gemini, open-source agents) should be able to use the wiki tools without reading external documentation.
361
362
Each tool's MCP description should include:
363
- What it does
364
- Parameter semantics (e.g., "path is like `Actors/Iran`, not a filesystem path")
365
- What the return format looks like
366
- Common next actions ("use `list_notes` to find available pages if you don't know the path")
367
368
The bootstrap template's Meta/Wiki Usage Guide provides Claude-specific conventions (session protocol, gardening duties), but the MCP tools themselves should work without it. The guide is optimization, not a prerequisite.
369
370
---
371
372
## Rate Limiting and Abuse Prevention
373
374
**Launch**: OAuth-only accounts + tier limits (1 wiki, 500 pages, 3 collaborators) provide sufficient abuse prevention at low traffic. Public wiki routes are the only unauthenticated surface — acceptable risk at launch with near-zero users.
375
376
**Post-launch (when traffic justifies it)**: AWS WAF on API Gateway and CloudFront. IP-based rate limiting, geographic blocking, bot control, OWASP Top 10 managed rule sets. Adds ~$5-10/mo. Deploy when there's real traffic to protect.
377
378
**Per-user rate limiting (premium launch)**: When premium tier ships, add per-user throttling on API and MCP endpoints via API Gateway usage plans or WAF custom rules. Define specific limits when the need materializes.
379
380
---
381
382
## Open Questions
383
384
1. **EFS + Lambda performance**: The key Phase 0 question. Does EFS latency for git operations meet targets (<500ms read, <1s write warm)? Does VPC cold start stay under 5s total?
385
386
2. **Otterwiki on Lambda feasibility**: Otterwiki has filesystem assumptions beyond the git repo (config files, static assets). How much Mangum adaptation is needed? EFS satisfies most filesystem assumptions, but Flask-on-Lambda via Mangum still requires testing.
387
388
3. **Lambda package size**: Otterwiki + gitpython + FAISS + FastMCP + Mangum. If over 250MB zip limit, use Lambda container images (up to 10GB).
389
390
4. **Git library choice**: gitpython shells out to `git` (binary dependency — verify availability in Lambda runtime). dulwich is pure Python (no binary, different API, possibly slower). dulwich avoids the binary question entirely.
391
392
5. **MCP Streamable HTTP timeouts**: API Gateway caps at 29s. Most MCP operations complete in <5s, but semantic search with embedding generation could approach 10–15s. Verify this isn't a problem.
393
394
6. **Platform JWT signing key management**: RS256 keypair in Secrets Manager. Need to define key rotation strategy — do we support multiple valid keys (JWKS with `kid` header) for zero-downtime rotation, or is manual rotation with a maintenance window acceptable for MVP?
395
396
7. **WorkOS + FastMCP integration on Lambda**: The FastMCP WorkOS integration is documented but needs validation in our specific setup (Lambda + API Gateway + VPC). Known friction points: `client_secret_basic` default may conflict with some MCP clients, no RFC 8707 resource indicator support. Validate in Phase 0.
397
398
8. **Apple provider sub retrieval**: WorkOS exposes raw OAuth provider `sub` claims via API for Google, GitHub, Microsoft. Apple is undocumented. If we can't get Apple's raw sub, Apple users can't be migrated off WorkOS without re-authenticating. Verify in Phase 0.
399
400
9. **Otterwiki licensing**: MIT licensed — permissive, should be fine for commercial use. Confirm no additional contributor agreements or trademark restrictions.
401
fec2d6 Claude (MCP) 2026-03-14 20:15:37
[mcp] Update Operations: open question 10 - VPC endpoint cost concern resolved"
402
10. **VPC endpoint costs** (resolved): SQS and Bedrock interface endpoints have been eliminated by switching to DynamoDB Streams (for async reindexing) and local MiniLM embeddings (for semantic search). The only remaining interface endpoint is Secrets Manager (~$7/mo/AZ, introduced in Phase 4). See [[Design/Async_Embedding_Pipeline]].