frontier-os-app-builder 1.1.0 → 1.2.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/LICENSE +21 -0
- package/README.md +25 -0
- package/agents/fos-executor.md +22 -65
- package/agents/fos-plan-checker.md +13 -12
- package/agents/fos-planner.md +20 -67
- package/agents/fos-researcher.md +14 -10
- package/agents/fos-verifier.md +11 -5
- package/bin/fos-tools.cjs +48 -11
- package/bin/install.js +8 -5
- package/commands/fos/add-feature.md +1 -2
- package/commands/fos/discuss.md +0 -1
- package/commands/fos/new-app.md +1 -3
- package/commands/fos/new-milestone.md +1 -1
- package/commands/fos/plan.md +0 -2
- package/package.json +7 -1
- package/references/app-patterns.md +46 -28
- package/references/deployment.md +40 -74
- package/references/module-index.md +32 -0
- package/references/sdk/chain.md +92 -0
- package/references/sdk/communities.md +159 -0
- package/references/sdk/events.md +212 -0
- package/references/sdk/init.md +126 -0
- package/references/sdk/navigation.md +49 -0
- package/references/sdk/offices.md +76 -0
- package/references/sdk/partnerships.md +111 -0
- package/references/sdk/storage.md +44 -0
- package/references/sdk/thirdparty.md +240 -0
- package/references/sdk/token-amount.md +99 -0
- package/references/sdk/types.md +27 -0
- package/references/sdk/ui-utils.md +39 -0
- package/references/sdk/user.md +208 -0
- package/references/sdk/wallet.md +334 -0
- package/references/verification-rules.md +18 -18
- package/templates/app/frontier-services.tsx +75 -18
- package/templates/app/layout.tsx +19 -9
- package/templates/app/package.json +2 -1
- package/templates/app/public/favicon.svg +3 -0
- package/templates/app/sdk-context.tsx +7 -9
- package/templates/app/sdk-services.tsx +92 -117
- package/templates/app/vercel.json +8 -47
- package/templates/state/plan.md +32 -14
- package/templates/state/roadmap.md +2 -2
- package/templates/state/summary.md +26 -29
- package/workflows/add-feature.md +6 -1
- package/workflows/discuss.md +9 -3
- package/workflows/execute-plan.md +3 -3
- package/workflows/execute.md +17 -6
- package/workflows/new-app.md +54 -18
- package/workflows/new-milestone.md +9 -2
- package/workflows/plan.md +14 -5
- package/workflows/ship.md +26 -10
- package/workflows/status.md +0 -1
- package/references/module-inference.md +0 -348
- package/references/sdk-surface.md +0 -1600
- package/templates/app/main-simple-standalone.tsx +0 -19
- package/templates/app/main-simple.tsx +0 -19
- package/templates/state/manifest.json +0 -12
package/references/deployment.md
CHANGED
|
@@ -18,13 +18,6 @@ All Frontier OS apps deploy to Vercel. The `vercel.json` file is identical acros
|
|
|
18
18
|
"headers": [
|
|
19
19
|
{
|
|
20
20
|
"source": "/(.*)",
|
|
21
|
-
"has": [
|
|
22
|
-
{
|
|
23
|
-
"type": "header",
|
|
24
|
-
"key": "Origin",
|
|
25
|
-
"value": "https://os.frontiertower.io"
|
|
26
|
-
}
|
|
27
|
-
],
|
|
28
21
|
"headers": [
|
|
29
22
|
{
|
|
30
23
|
"key": "Access-Control-Allow-Origin",
|
|
@@ -37,54 +30,22 @@ All Frontier OS apps deploy to Vercel. The `vercel.json` file is identical acros
|
|
|
37
30
|
{
|
|
38
31
|
"key": "Access-Control-Allow-Headers",
|
|
39
32
|
"value": "Content-Type"
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"source": "/(.*)",
|
|
45
|
-
"has": [
|
|
46
|
-
{
|
|
47
|
-
"type": "header",
|
|
48
|
-
"key": "Origin",
|
|
49
|
-
"value": "https://sandbox.os.frontiertower.io"
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
"headers": [
|
|
53
|
-
{
|
|
54
|
-
"key": "Access-Control-Allow-Origin",
|
|
55
|
-
"value": "https://sandbox.os.frontiertower.io"
|
|
56
33
|
},
|
|
57
34
|
{
|
|
58
|
-
"key": "
|
|
59
|
-
"value": "
|
|
35
|
+
"key": "Content-Security-Policy",
|
|
36
|
+
"value": "frame-ancestors https://os.frontiertower.io https://sandbox.os.frontiertower.io http://localhost:5173;"
|
|
60
37
|
},
|
|
61
38
|
{
|
|
62
|
-
"key": "
|
|
63
|
-
"value": "
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
"source": "/(.*)",
|
|
69
|
-
"has": [
|
|
70
|
-
{
|
|
71
|
-
"type": "header",
|
|
72
|
-
"key": "Origin",
|
|
73
|
-
"value": "http://localhost:5173"
|
|
74
|
-
}
|
|
75
|
-
],
|
|
76
|
-
"headers": [
|
|
77
|
-
{
|
|
78
|
-
"key": "Access-Control-Allow-Origin",
|
|
79
|
-
"value": "http://localhost:5173"
|
|
39
|
+
"key": "X-Content-Type-Options",
|
|
40
|
+
"value": "nosniff"
|
|
80
41
|
},
|
|
81
42
|
{
|
|
82
|
-
"key": "
|
|
83
|
-
"value": "
|
|
43
|
+
"key": "Referrer-Policy",
|
|
44
|
+
"value": "strict-origin-when-cross-origin"
|
|
84
45
|
},
|
|
85
46
|
{
|
|
86
|
-
"key": "
|
|
87
|
-
"value": "
|
|
47
|
+
"key": "Permissions-Policy",
|
|
48
|
+
"value": "camera=(), microphone=(), geolocation=()"
|
|
88
49
|
}
|
|
89
50
|
]
|
|
90
51
|
}
|
|
@@ -92,15 +53,15 @@ All Frontier OS apps deploy to Vercel. The `vercel.json` file is identical acros
|
|
|
92
53
|
}
|
|
93
54
|
```
|
|
94
55
|
|
|
95
|
-
###
|
|
56
|
+
### One Header Block + CSP `frame-ancestors`
|
|
96
57
|
|
|
97
|
-
|
|
58
|
+
A single unconditional header block applies CORS for the production origin plus the security headers to every response. Embedding by all three Frontier origins is granted by the `Content-Security-Policy: frame-ancestors` directive (which lists all three) — `frame-ancestors` is what actually governs iframe embedding, not per-origin CORS reflection. This replaces the older pattern of one `has`-matched CORS block per origin.
|
|
98
59
|
|
|
99
60
|
---
|
|
100
61
|
|
|
101
62
|
## Allowed Origins
|
|
102
63
|
|
|
103
|
-
The Frontier Wallet PWA runs at these 3 origins. Apps must allow
|
|
64
|
+
The Frontier Wallet PWA runs at these 3 origins. Apps must allow all of them to embed the app via the CSP `frame-ancestors` directive:
|
|
104
65
|
|
|
105
66
|
| Origin | Environment | Description |
|
|
106
67
|
| ----------------------------------------- | ------------ | -------------------------------------------------------------- |
|
|
@@ -108,7 +69,7 @@ The Frontier Wallet PWA runs at these 3 origins. Apps must allow CORS from all o
|
|
|
108
69
|
| `https://sandbox.os.frontiertower.io` | Sandbox | Sandbox environment |
|
|
109
70
|
| `https://os.frontiertower.io` | Production | Production ready |
|
|
110
71
|
|
|
111
|
-
These origins are also hardcoded in the SDK at `@frontiertower/frontier-sdk/ui-utils/detection.ts` as `ALLOWED_ORIGINS
|
|
72
|
+
These origins are also hardcoded in the SDK at `@frontiertower/frontier-sdk/ui-utils/detection.ts` as `ALLOWED_ORIGINS` (exactly these 3). Note: `isInFrontierApp()` no longer consults this list -- it returns `window.self !== window.top` -- so `ALLOWED_ORIGINS` is informational for CORS/CSP only.
|
|
112
73
|
|
|
113
74
|
The `isInFrontierApp()` function checks `window.self !== window.top` to detect if the app is running inside the Frontier Wallet iframe. The `getParentOrigin()` function resolves the parent frame's origin via `document.referrer` or `window.parent.location.origin`.
|
|
114
75
|
|
|
@@ -118,16 +79,16 @@ The `isInFrontierApp()` function checks `window.self !== window.top` to detect i
|
|
|
118
79
|
|
|
119
80
|
## Security Headers
|
|
120
81
|
|
|
121
|
-
|
|
82
|
+
The `vercel.json` above already ships these alongside CORS — every app should keep them:
|
|
122
83
|
|
|
123
|
-
| Header |
|
|
84
|
+
| Header | Value (shipped in vercel.json) | Purpose |
|
|
124
85
|
| ---------------------------- | -------------------------------------------------- | ------------------------------------------- |
|
|
125
|
-
| `Content-Security-Policy` |
|
|
86
|
+
| `Content-Security-Policy` | `frame-ancestors https://os.frontiertower.io https://sandbox.os.frontiertower.io http://localhost:5173;` (the 3 live origins) | Restricts who may embed the app |
|
|
126
87
|
| `X-Content-Type-Options` | `nosniff` | Prevents MIME-type sniffing |
|
|
127
88
|
| `Referrer-Policy` | `strict-origin-when-cross-origin` | Controls referrer information leakage |
|
|
128
|
-
| `Permissions-Policy` |
|
|
89
|
+
| `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` | Disables unused browser APIs |
|
|
129
90
|
|
|
130
|
-
The `frame-ancestors` CSP directive is critical because apps load inside the PWA's iframe. Without it, the browser may block the embed.
|
|
91
|
+
The `frame-ancestors` CSP directive is critical because apps load inside the PWA's iframe. Without it, the browser may block the embed. The CSP is intentionally limited to `frame-ancestors` so it never blocks app resources (e.g. the Google Fonts stylesheet the template loads); apps that self-host all assets may tighten it further.
|
|
131
92
|
|
|
132
93
|
---
|
|
133
94
|
|
|
@@ -142,7 +103,7 @@ The recommended way is to use the OS Developer app in the Frontier AppStore. The
|
|
|
142
103
|
1. **Get developer access** -- contact support@frontiertower.io to be added as a developer manager.
|
|
143
104
|
2. **Get your developer profile** -- install the OS Developer app from the AppStore, or call `GET /third-party/developers/`.
|
|
144
105
|
3. **Rotate your API key** immediately after receiving it: `POST /third-party/developers/{developer_id}/rotate-key/`. Store the new key securely.
|
|
145
|
-
4. **Create the app** -- via OS Developer or `POST /third-party/apps/` with
|
|
106
|
+
4. **Create the app** -- via OS Developer (`sdk.getThirdParty().createApp(...)`) or `POST /third-party/apps/` with body `{ url, cnameEntry, txtEntry?, permissions: string[], permissionDisclaimer }` (OS Developer additionally sends `developer: <id>`). App `name`, `description`, and `icon` are NOT sent -- they are auto-fetched from the app URL's HTML metadata (`<title>`, `<meta name="description">`, `<link rel="icon">`).
|
|
146
107
|
|
|
147
108
|
### App Status Lifecycle
|
|
148
109
|
|
|
@@ -167,24 +128,29 @@ When registering, declare the SDK permissions your app requires:
|
|
|
167
128
|
```typescript
|
|
168
129
|
const APP_REGISTRY: AppMetadata[] = [
|
|
169
130
|
{
|
|
170
|
-
id: '
|
|
171
|
-
url: 'https://
|
|
172
|
-
|
|
173
|
-
version: '1.0.0',
|
|
131
|
+
id: 'ifnd-converter',
|
|
132
|
+
url: 'https://ifnd-converter.apps.frontiertower.io',
|
|
133
|
+
icon: '/svgs/ifnd_converter.svg',
|
|
174
134
|
developer: {
|
|
175
135
|
name: 'Developer Name',
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
permissions: {
|
|
179
|
-
wallet: true,
|
|
180
|
-
storage: true,
|
|
181
|
-
notifications: false,
|
|
136
|
+
url: 'https://frontiertower.io',
|
|
137
|
+
description: 'Made with love by the Frontier Tower Action Team',
|
|
182
138
|
},
|
|
139
|
+
permissions: [
|
|
140
|
+
'wallet:getBalance',
|
|
141
|
+
'wallet:getAddress',
|
|
142
|
+
'wallet:executeBatchCall',
|
|
143
|
+
'wallet:executeCall',
|
|
144
|
+
'chain:getCurrentChainConfig',
|
|
145
|
+
],
|
|
146
|
+
permissionDisclaimer:
|
|
147
|
+
'This app accesses your wallet address and balance and executes the conversion calls.',
|
|
148
|
+
// optional: excludedAppStages?, requiresCitizenship?, requiresAdmin?
|
|
183
149
|
} as AppMetadata,
|
|
184
150
|
];
|
|
185
151
|
```
|
|
186
152
|
|
|
187
|
-
Permissions must match
|
|
153
|
+
Permissions are a flat array of `module:method` strings -- each entry must match an SDK method actually called in source code. `name`, `description`, and `icon` are optional in `AppMetadata` (auto-fetched from the app's HTML when omitted). There is no `origin`, `version`, or `developer.verified` field, and there is no `notifications` permission. The fos-verifier agent enforces the permission-to-source match (see [verification-rules.md](verification-rules.md)).
|
|
188
154
|
|
|
189
155
|
---
|
|
190
156
|
|
|
@@ -210,15 +176,15 @@ VITE_API_URL=https://api.example.com
|
|
|
210
176
|
|
|
211
177
|
## DNS Configuration
|
|
212
178
|
|
|
213
|
-
Apps are hosted on the `
|
|
179
|
+
Apps are hosted on the `apps.frontiertower.io` subdomain.
|
|
214
180
|
|
|
215
181
|
### Domain Pattern
|
|
216
182
|
|
|
217
183
|
```
|
|
218
|
-
<app-name>.
|
|
184
|
+
<app-name>.apps.frontiertower.io
|
|
219
185
|
```
|
|
220
186
|
|
|
221
|
-
Example: `kickstarter.
|
|
187
|
+
Example: `kickstarter.apps.frontiertower.io`
|
|
222
188
|
|
|
223
189
|
### DNS Entries
|
|
224
190
|
|
|
@@ -226,12 +192,12 @@ Two DNS records are needed:
|
|
|
226
192
|
|
|
227
193
|
1. **CNAME** -- points the subdomain to the Vercel deployment:
|
|
228
194
|
```
|
|
229
|
-
<app-name>.
|
|
195
|
+
<app-name>.apps.frontiertower.io CNAME cname.vercel-dns.com
|
|
230
196
|
```
|
|
231
197
|
|
|
232
198
|
2. **TXT** -- Vercel domain verification:
|
|
233
199
|
```
|
|
234
|
-
_vercel.<app-name>.
|
|
200
|
+
_vercel.<app-name>.apps.frontiertower.io TXT vc-domain-verify=<token>
|
|
235
201
|
```
|
|
236
202
|
|
|
237
203
|
Configure the custom domain in the Vercel dashboard after DNS propagation. Vercel automatically provisions an SSL certificate.
|
|
@@ -331,7 +297,7 @@ Call `POST /third-party/webhooks/{webhook_id}/rotate-key/`. Deliveries immediate
|
|
|
331
297
|
After deploying, verify CORS is working:
|
|
332
298
|
|
|
333
299
|
```bash
|
|
334
|
-
curl -I https://<app-name>.
|
|
300
|
+
curl -I https://<app-name>.apps.frontiertower.io \
|
|
335
301
|
-H "Origin: https://os.frontiertower.io"
|
|
336
302
|
|
|
337
303
|
# Should include:
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# SDK Module Index
|
|
2
|
+
|
|
3
|
+
Maps app descriptions to Frontier SDK modules. The CLI (`fos-tools.cjs infer-modules`) does keyword matching programmatically — this file documents the algorithm and serves as an index to per-module reference files.
|
|
4
|
+
|
|
5
|
+
## Inference Algorithm
|
|
6
|
+
|
|
7
|
+
This mirrors `cmdInferModules` in `fos-tools.cjs` exactly:
|
|
8
|
+
|
|
9
|
+
1. Lowercase the entire description (`description.toLowerCase()`) — no tokenization or word splitting.
|
|
10
|
+
2. For each SDK module, substring-match its trigger keywords against the lowercased description with `String.includes()` (keywords are listed in each module's reference file under `references/sdk/`). Because matching is by substring, multi-word phrases like `send money`, `access control`, and `api key` work, and a keyword can match inside a larger word (e.g. `fund` matches within `refund`).
|
|
11
|
+
3. Always include Storage and Chain (the base modules — every app needs these).
|
|
12
|
+
4. Include User if User's own keywords match, or if any of Wallet, Events, Communities, Partnerships, or Offices matched. User is NOT added by ThirdParty, Navigation, Storage, or Chain alone.
|
|
13
|
+
5. Present the inferred modules for user confirmation.
|
|
14
|
+
|
|
15
|
+
## Module Quick Reference
|
|
16
|
+
|
|
17
|
+
| Module | Reference File | Primary Use Case |
|
|
18
|
+
|--------|---------------|-----------------|
|
|
19
|
+
| Wallet | `references/sdk/wallet.md` | Payments, transfers, FND/iFND, fiat on/off-ramp |
|
|
20
|
+
| Storage | `references/sdk/storage.md` | Key-value persistence, preferences |
|
|
21
|
+
| Chain | `references/sdk/chain.md` | Network config, contract addresses |
|
|
22
|
+
| User | `references/sdk/user.md` | Profiles, access controls, membership |
|
|
23
|
+
| Communities | `references/sdk/communities.md` | Groups, internships, member management |
|
|
24
|
+
| Partnerships | `references/sdk/partnerships.md` | Sponsors, passes, brand partnerships |
|
|
25
|
+
| Events | `references/sdk/events.md` | Calendar, rooms, bookings, RSVPs |
|
|
26
|
+
| Offices | `references/sdk/offices.md` | Physical access passes, building entry |
|
|
27
|
+
| ThirdParty | `references/sdk/thirdparty.md` | Developer tools, webhooks, API keys |
|
|
28
|
+
| Navigation | `references/sdk/navigation.md` | Deep links, cross-app navigation |
|
|
29
|
+
|
|
30
|
+
## After Inference
|
|
31
|
+
|
|
32
|
+
Once modules are confirmed, read only the relevant `references/sdk/<module>.md` files for detailed method signatures, types, and permissions. Always include `references/sdk/init.md` and `references/sdk/types.md` as shared context. For any app that reads, displays, transfers, or swaps FND amounts, also read `references/sdk/token-amount.md` — FND amounts are `bigint` base units bridged to/from display strings via `formatAmount()`/`parseAmount()`.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Chain Module
|
|
2
|
+
|
|
3
|
+
**Trigger keywords:** network, chain, blockchain, contract, smart contract, on-chain, token address, stablecoin
|
|
4
|
+
|
|
5
|
+
Access via `sdk.getChain()`. Query and switch blockchain networks.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Methods
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
getCurrentNetwork(): Promise<string>
|
|
13
|
+
```
|
|
14
|
+
Returns the current network identifier (e.g. `'base'`, `'base-sepolia'`). Permission: `chain:getCurrentNetwork`
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
getAvailableNetworks(): Promise<string[]>
|
|
18
|
+
```
|
|
19
|
+
Returns all network identifiers the app can switch to. Permission: `chain:getAvailableNetworks`
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
switchNetwork(network: string): Promise<void>
|
|
23
|
+
```
|
|
24
|
+
Switch active blockchain network. Affects all subsequent wallet operations. Permission: `chain:switchNetwork`
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
getCurrentChainConfig(): Promise<ChainConfig>
|
|
28
|
+
```
|
|
29
|
+
Returns full chain configuration for the current network. Permission: `chain:getCurrentChainConfig`
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
getContractAddresses(): Promise<{
|
|
33
|
+
fnd: string;
|
|
34
|
+
iFnd: string | null;
|
|
35
|
+
paymentRouter: string;
|
|
36
|
+
subscriptionManager: string;
|
|
37
|
+
}>
|
|
38
|
+
```
|
|
39
|
+
Returns addresses for FND, iFND (may be null), PaymentRouter, and SubscriptionManager contracts on the current chain. Permission: `chain:getContractAddresses`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Types
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
enum Underlying {
|
|
47
|
+
USD = "USD",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface Token {
|
|
51
|
+
name: string;
|
|
52
|
+
symbol: string;
|
|
53
|
+
decimals: number;
|
|
54
|
+
address: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface StableCoin extends Token {
|
|
58
|
+
underlying: Underlying;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface ChainConfig {
|
|
62
|
+
id: number;
|
|
63
|
+
name: string;
|
|
64
|
+
network: string;
|
|
65
|
+
bridgeSwapRouterFactoryAddress: string;
|
|
66
|
+
uniswapV3FactoryAddress: string;
|
|
67
|
+
nativeCurrency: {
|
|
68
|
+
name: string;
|
|
69
|
+
symbol: string;
|
|
70
|
+
decimals: number;
|
|
71
|
+
};
|
|
72
|
+
blockExplorer: {
|
|
73
|
+
name: string;
|
|
74
|
+
url: string;
|
|
75
|
+
};
|
|
76
|
+
stableCoins: StableCoin[];
|
|
77
|
+
supportedTokens: Token[];
|
|
78
|
+
testnet: boolean;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Permissions (5)
|
|
85
|
+
|
|
86
|
+
| Permission | Description |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `chain:getCurrentNetwork` | Get current network name |
|
|
89
|
+
| `chain:getAvailableNetworks` | Get list of available networks |
|
|
90
|
+
| `chain:switchNetwork` | Switch to a different network |
|
|
91
|
+
| `chain:getCurrentChainConfig` | Get full chain configuration |
|
|
92
|
+
| `chain:getContractAddresses` | Get FND, iFND, PaymentRouter, SubscriptionManager addresses |
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Communities Module
|
|
2
|
+
|
|
3
|
+
**Trigger keywords:** community, group, team, club, internship, intern, cohort, reassign, transfer member, collective, society
|
|
4
|
+
|
|
5
|
+
Access via `sdk.getCommunities()`. Manage communities, internship passes, and member reassignment requests.
|
|
6
|
+
|
|
7
|
+
Community listing is public. Internship passes require authentication, an active subscription, and community manager status. Reassign requests require authentication; creating requires managing the member's current community, accepting requires managing the target community. Superusers can access everything.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Methods
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
listCommunities(payload?: ListCommunitiesParams): Promise<PaginatedResponse<Community>>
|
|
15
|
+
```
|
|
16
|
+
List all visible communities, paginated. Permission: `communities:listCommunities`
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
getCommunity(payload: { idOrSlug: string | number }): Promise<Community>
|
|
20
|
+
```
|
|
21
|
+
Get a community by numeric ID or slug string. Permission: `communities:getCommunity`
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
createInternshipPass(payload: CreateInternshipPassRequest): Promise<InternshipPass>
|
|
25
|
+
```
|
|
26
|
+
Create an internship pass. Auto-creates an inactive account if the user does not exist. Permission: `communities:createInternshipPass`
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
listInternshipPasses(payload?: ListInternshipPassesParams): Promise<PaginatedResponse<InternshipPass>>
|
|
30
|
+
```
|
|
31
|
+
List internship passes for managed communities. Active only by default; set `includeRevoked: true` to include revoked. Permission: `communities:listInternshipPasses`
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
getInternshipPass(payload: { id: number }): Promise<InternshipPass>
|
|
35
|
+
```
|
|
36
|
+
Get an internship pass by ID. Permission: `communities:getInternshipPass`
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
revokeInternshipPass(payload: { id: number }): Promise<void>
|
|
40
|
+
```
|
|
41
|
+
Revoke an internship pass. Cannot revoke an already-revoked pass. Permission: `communities:revokeInternshipPass`
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
createReassignRequest(payload: CreateReassignRequestPayload): Promise<ReassignRequest>
|
|
45
|
+
```
|
|
46
|
+
Request to move a member to a different community. Caller must manage the member's current community. Permission: `communities:createReassignRequest`
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
listReassignRequests(payload?: ListReassignRequestsParams): Promise<PaginatedResponse<ReassignRequest>>
|
|
50
|
+
```
|
|
51
|
+
List pending reassign requests visible to the caller. Permission: `communities:listReassignRequests`
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
getReassignRequest(payload: { id: number }): Promise<ReassignRequest>
|
|
55
|
+
```
|
|
56
|
+
Get a reassign request by ID. Permission: `communities:getReassignRequest`
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
acceptReassignRequest(payload: { id: number }): Promise<ReassignRequest>
|
|
60
|
+
```
|
|
61
|
+
Accept a reassign request. Moves the member to the target community. Only target community managers (or superusers) can accept. Permission: `communities:acceptReassignRequest`
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
rejectReassignRequest(payload: { id: number }): Promise<void>
|
|
65
|
+
```
|
|
66
|
+
Reject a reassign request. Only pending requests can be rejected. Permission: `communities:rejectReassignRequest`
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Types
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
interface Community {
|
|
74
|
+
id: number;
|
|
75
|
+
name: string;
|
|
76
|
+
description: string;
|
|
77
|
+
slug: string;
|
|
78
|
+
iconName: string;
|
|
79
|
+
splashVideo: string | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface ListCommunitiesParams {
|
|
83
|
+
limit?: number;
|
|
84
|
+
offset?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type InternshipPassStatus = 'active' | 'revoked';
|
|
88
|
+
|
|
89
|
+
interface InternshipPass {
|
|
90
|
+
id: number;
|
|
91
|
+
email: string;
|
|
92
|
+
firstName: string;
|
|
93
|
+
lastName: string;
|
|
94
|
+
community: number;
|
|
95
|
+
communityName: string;
|
|
96
|
+
status: InternshipPassStatus;
|
|
97
|
+
createdAt: string;
|
|
98
|
+
revokedAt: string | null;
|
|
99
|
+
updatedAt: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface CreateInternshipPassRequest {
|
|
103
|
+
email: string;
|
|
104
|
+
firstName: string;
|
|
105
|
+
lastName: string;
|
|
106
|
+
community: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface ListInternshipPassesParams {
|
|
110
|
+
limit?: number;
|
|
111
|
+
offset?: number;
|
|
112
|
+
includeRevoked?: boolean;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
type ReassignRequestStatus = 'pending' | 'accepted' | 'rejected';
|
|
116
|
+
|
|
117
|
+
interface ReassignRequest {
|
|
118
|
+
id: number;
|
|
119
|
+
requester: number;
|
|
120
|
+
requesterEmail: string;
|
|
121
|
+
member: number;
|
|
122
|
+
memberEmail: string;
|
|
123
|
+
targetCommunity: number;
|
|
124
|
+
targetCommunityName: string;
|
|
125
|
+
status: ReassignRequestStatus;
|
|
126
|
+
createdAt: string;
|
|
127
|
+
resolvedAt: string | null;
|
|
128
|
+
resolvedBy: number | null;
|
|
129
|
+
resolvedByEmail: string | null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface CreateReassignRequestPayload {
|
|
133
|
+
memberEmail: string;
|
|
134
|
+
targetCommunity: number;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface ListReassignRequestsParams {
|
|
138
|
+
limit?: number;
|
|
139
|
+
offset?: number;
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Permissions (11)
|
|
146
|
+
|
|
147
|
+
| Permission | Description |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `communities:listCommunities` | List all visible communities (paginated) |
|
|
150
|
+
| `communities:getCommunity` | Get a community by ID or slug |
|
|
151
|
+
| `communities:createInternshipPass` | Create an internship pass for a managed community |
|
|
152
|
+
| `communities:listInternshipPasses` | List internship passes for managed communities |
|
|
153
|
+
| `communities:getInternshipPass` | Retrieve an internship pass by ID |
|
|
154
|
+
| `communities:revokeInternshipPass` | Revoke an internship pass |
|
|
155
|
+
| `communities:createReassignRequest` | Create a member reassignment request |
|
|
156
|
+
| `communities:listReassignRequests` | List pending reassignment requests |
|
|
157
|
+
| `communities:getReassignRequest` | Retrieve a reassignment request by ID |
|
|
158
|
+
| `communities:acceptReassignRequest` | Accept a reassignment request (moves member) |
|
|
159
|
+
| `communities:rejectReassignRequest` | Reject a reassignment request |
|