ftown 0.20.6 → 0.20.7
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/dist/attention-prompt-protocol.d.ts +2 -2
- package/dist/attention-prompt-protocol.js +1 -1
- package/dist/centrifugo-client.js +0 -1
- package/dist/centrifugo-client.js.map +1 -1
- package/dist/command-rpc.d.ts +0 -1
- package/dist/command-rpc.js +3 -24
- package/dist/command-rpc.js.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/security/bridge/account-state.d.ts +0 -4
- package/dist/security/bridge/direct.js +0 -2
- package/dist/security/bridge/direct.js.map +1 -1
- package/dist/security/bridge/execute.js +1 -6
- package/dist/security/bridge/execute.js.map +1 -1
- package/dist/security/bridge/identity.d.ts +0 -3
- package/dist/security/bridge/metadata.d.ts +0 -2
- package/dist/security/bridge/metadata.js +1 -1
- package/dist/security/bridge/metadata.js.map +1 -1
- package/dist/security/bridge/permissions.js +3 -11
- package/dist/security/bridge/permissions.js.map +1 -1
- package/dist/security/bridge/policy.d.ts +4 -7
- package/dist/security/bridge/policy.js +35 -90
- package/dist/security/bridge/policy.js.map +1 -1
- package/dist/security/bridge/security.d.ts +1 -11
- package/dist/security/bridge/security.js +7 -79
- package/dist/security/bridge/security.js.map +1 -1
- package/dist/security/crypto.js +2 -2
- package/dist/security/crypto.js.map +1 -1
- package/dist/security/protocol.d.ts +5 -126
- package/dist/types.d.ts +1 -1
- package/dist/update-effects.js +1 -1
- package/dist/update-effects.js.map +1 -1
- package/package.json +4 -12
- package/skills/ftown/SKILL.md +9 -13
- package/skills/ftown/references/sessions.md +4 -20
- package/dist/mcp/fleet.d.ts +0 -67
- package/dist/mcp/fleet.js +0 -298
- package/dist/mcp/fleet.js.map +0 -1
- package/dist/mcp/http.d.ts +0 -42
- package/dist/mcp/http.js +0 -350
- package/dist/mcp/http.js.map +0 -1
- package/dist/mcp/legacy-relay.d.ts +0 -3
- package/dist/mcp/legacy-relay.js +0 -6
- package/dist/mcp/legacy-relay.js.map +0 -1
- package/dist/mcp/mcp-key-store.d.ts +0 -52
- package/dist/mcp/mcp-key-store.js +0 -207
- package/dist/mcp/mcp-key-store.js.map +0 -1
- package/dist/mcp/oauth-store.d.ts +0 -17
- package/dist/mcp/oauth-store.js +0 -58
- package/dist/mcp/oauth-store.js.map +0 -1
- package/dist/mcp/oauth.d.ts +0 -83
- package/dist/mcp/oauth.js +0 -311
- package/dist/mcp/oauth.js.map +0 -1
- package/dist/mcp/relay-handler.d.ts +0 -2
- package/dist/mcp/relay-handler.js +0 -8
- package/dist/mcp/relay-handler.js.map +0 -1
- package/dist/mcp/relay.d.ts +0 -13
- package/dist/mcp/relay.js +0 -95
- package/dist/mcp/relay.js.map +0 -1
- package/dist/mcp/secure-client.d.ts +0 -23
- package/dist/mcp/secure-client.js +0 -124
- package/dist/mcp/secure-client.js.map +0 -1
- package/dist/mcp/security-events.d.ts +0 -49
- package/dist/mcp/security-events.js +0 -211
- package/dist/mcp/security-events.js.map +0 -1
- package/dist/mcp/server.d.ts +0 -13
- package/dist/mcp/server.js +0 -858
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/test-support.d.ts +0 -32
- package/dist/mcp/test-support.js +0 -120
- package/dist/mcp/test-support.js.map +0 -1
- package/dist/mcp-cli.d.ts +0 -2
- package/dist/mcp-cli.js +0 -105
- package/dist/mcp-cli.js.map +0 -1
- package/dist/security/bridge/audit.d.ts +0 -37
- package/dist/security/bridge/audit.js +0 -186
- package/dist/security/bridge/audit.js.map +0 -1
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import { legacyDateTimeSchema } from '../zod-compat.js';
|
|
2
|
-
import { randomBytes } from 'node:crypto';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import { generateEndpoint, importEndpoint, importPublicKey, SecurityError } from '../security/crypto.js';
|
|
5
|
-
const MAX_RECORD_BYTES = 65_536;
|
|
6
|
-
const MAX_ACTIVE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
7
|
-
const endpointSchema = z.object({ version: z.literal(1), id: z.string().regex(/^[A-Za-z0-9_-]{43}$/), ownerId: z.string().guid(), kind: z.enum(['bridge', 'browser', 'mcp', 'local-cli']), publicKey: z.string().regex(/^[A-Za-z0-9_-]{87}$/) }).strict();
|
|
8
|
-
const pinSchema = z.object({ bridgeId: z.string().regex(/^[A-Za-z0-9_-]{1,200}$/), endpoint: endpointSchema, permissions: z.array(z.enum(['read', 'control'])).min(1).max(2) }).strict();
|
|
9
|
-
const keySchema = z.object({ kty: z.literal('EC'), crv: z.literal('P-256'), x: z.string().regex(/^[A-Za-z0-9_-]{43}$/), y: z.string().regex(/^[A-Za-z0-9_-]{43}$/), d: z.string().regex(/^[A-Za-z0-9_-]{43}$/) }).strict();
|
|
10
|
-
const storedSchema = z.object({
|
|
11
|
-
version: z.literal(1), ownerId: z.string().guid(), requestId: z.string().regex(/^[A-Za-z0-9_-]{43}$/), grantId: z.string().regex(/^[A-Za-z0-9_-]{43}$/),
|
|
12
|
-
endpoint: endpointSchema, privateKey: keySchema, bridges: z.array(pinSchema).max(64),
|
|
13
|
-
permissions: z.array(z.enum(['read', 'control'])).min(1).max(2),
|
|
14
|
-
pendingExpiresAt: legacyDateTimeSchema, activeExpiresAt: legacyDateTimeSchema, state: z.enum(['pending', 'approved', 'active', 'revoked']),
|
|
15
|
-
}).strict();
|
|
16
|
-
const safeUnavailable = () => new SecurityError('key_unavailable', 'MCP encryption identity is unavailable');
|
|
17
|
-
const b64 = (value) => Buffer.from(value).toString('base64url');
|
|
18
|
-
function from64(value, min, max = min) {
|
|
19
|
-
if (typeof value !== 'string' || !/^[A-Za-z0-9_-]+$/.test(value) || value.length > Math.ceil(max * 4 / 3))
|
|
20
|
-
throw safeUnavailable();
|
|
21
|
-
const decoded = Uint8Array.from(Buffer.from(value, 'base64url'));
|
|
22
|
-
if (decoded.length < min || decoded.length > max || b64(decoded) !== value)
|
|
23
|
-
throw safeUnavailable();
|
|
24
|
-
return decoded;
|
|
25
|
-
}
|
|
26
|
-
function context(row) {
|
|
27
|
-
return new TextEncoder().encode(JSON.stringify(['ftown/mcp-private-key/v1', row.version, row.ownerId, row.requestId, row.grantId, row.endpointId, row.expiresAt, row.keyId]));
|
|
28
|
-
}
|
|
29
|
-
function configKey(config) {
|
|
30
|
-
if (!/^[A-Za-z0-9_-]{1,64}$/.test(config.keyId) || config.key.byteLength !== 32)
|
|
31
|
-
throw new SecurityError('security_setup_required', 'MCP encryption wrapping key and key ID must be provisioned');
|
|
32
|
-
return crypto.subtle.importKey('raw', Uint8Array.from(config.key), 'AES-GCM', false, ['encrypt', 'decrypt']);
|
|
33
|
-
}
|
|
34
|
-
async function validatePins(pins, ownerId) {
|
|
35
|
-
if (pins.length > 64 || new Set(pins.map(pin => pin.bridgeId)).size !== pins.length || new Set(pins.map(pin => pin.endpoint.id)).size !== pins.length)
|
|
36
|
-
throw safeUnavailable();
|
|
37
|
-
for (const pin of pins) {
|
|
38
|
-
if (pin.endpoint.ownerId !== ownerId || pin.endpoint.kind !== 'bridge' || !pin.permissions.includes('read') || pin.permissions.some(permission => permission === 'admin'))
|
|
39
|
-
throw safeUnavailable();
|
|
40
|
-
await importPublicKey(pin.endpoint.publicKey);
|
|
41
|
-
if (b64(new Uint8Array(await crypto.subtle.digest('SHA-256', from64(pin.endpoint.publicKey, 65)))) !== pin.endpoint.id)
|
|
42
|
-
throw safeUnavailable();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function stored(identity, privateKey) {
|
|
46
|
-
const parsed = storedSchema.safeParse({
|
|
47
|
-
version: 1, ownerId: identity.ownerId, requestId: identity.requestId, grantId: identity.grantId,
|
|
48
|
-
endpoint: identity.identity.endpoint, privateKey: { kty: privateKey.kty, crv: privateKey.crv, x: privateKey.x, y: privateKey.y, d: privateKey.d },
|
|
49
|
-
bridges: identity.bridges, permissions: identity.permissions, pendingExpiresAt: identity.pendingExpiresAt,
|
|
50
|
-
activeExpiresAt: identity.activeExpiresAt, state: identity.state,
|
|
51
|
-
});
|
|
52
|
-
if (!parsed.success)
|
|
53
|
-
throw safeUnavailable();
|
|
54
|
-
return parsed.data;
|
|
55
|
-
}
|
|
56
|
-
export async function encryptMcpIdentity(identity, privateKey, config) {
|
|
57
|
-
const value = stored(identity, privateKey);
|
|
58
|
-
await importEndpoint(value.endpoint, value.privateKey);
|
|
59
|
-
await validatePins(value.bridges, value.ownerId);
|
|
60
|
-
if (value.endpoint.kind !== 'mcp' || value.endpoint.ownerId !== value.ownerId)
|
|
61
|
-
throw safeUnavailable();
|
|
62
|
-
const plaintext = new TextEncoder().encode(JSON.stringify(value));
|
|
63
|
-
if (plaintext.byteLength > MAX_RECORD_BYTES)
|
|
64
|
-
throw safeUnavailable();
|
|
65
|
-
const row = { version: 1, ownerId: value.ownerId, requestId: value.requestId, grantId: value.grantId, endpointId: value.endpoint.id, expiresAt: value.activeExpiresAt, keyId: config.keyId, nonce: b64(randomBytes(12)), ciphertext: '' };
|
|
66
|
-
const key = await configKey(config);
|
|
67
|
-
row.ciphertext = b64(new Uint8Array(await crypto.subtle.encrypt({ name: 'AES-GCM', iv: from64(row.nonce, 12), additionalData: context(row), tagLength: 128 }, key, plaintext)));
|
|
68
|
-
return row;
|
|
69
|
-
}
|
|
70
|
-
export async function decryptMcpIdentity(row, config) {
|
|
71
|
-
const key = await configKey(config);
|
|
72
|
-
try {
|
|
73
|
-
if (row.version !== 1 || row.keyId !== config.keyId || Object.keys(row).length !== 9)
|
|
74
|
-
throw safeUnavailable();
|
|
75
|
-
const plaintext = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: from64(row.nonce, 12), additionalData: context(row), tagLength: 128 }, key, from64(row.ciphertext, 16, MAX_RECORD_BYTES + 16));
|
|
76
|
-
const parsed = storedSchema.safeParse(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(plaintext)));
|
|
77
|
-
if (!parsed.success)
|
|
78
|
-
throw safeUnavailable();
|
|
79
|
-
const value = parsed.data;
|
|
80
|
-
if (value.ownerId !== row.ownerId || value.requestId !== row.requestId || value.grantId !== row.grantId || value.endpoint.id !== row.endpointId || value.activeExpiresAt !== row.expiresAt || value.endpoint.ownerId !== value.ownerId || value.endpoint.kind !== 'mcp')
|
|
81
|
-
throw safeUnavailable();
|
|
82
|
-
await validatePins(value.bridges, value.ownerId);
|
|
83
|
-
return { ownerId: value.ownerId, requestId: value.requestId, grantId: value.grantId, identity: await importEndpoint(value.endpoint, value.privateKey), bridges: value.bridges, permissions: value.permissions, pendingExpiresAt: value.pendingExpiresAt, activeExpiresAt: value.activeExpiresAt, state: value.state };
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
throw safeUnavailable();
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function dbEnvelope(row) {
|
|
90
|
-
if (row.envelope.ownerId !== row.owner_id || row.envelope.requestId !== row.request_id || row.envelope.grantId !== row.grant_id
|
|
91
|
-
|| row.envelope.endpointId !== row.endpoint_id || row.envelope.expiresAt !== row.expires_at.toISOString())
|
|
92
|
-
throw safeUnavailable();
|
|
93
|
-
return row.envelope;
|
|
94
|
-
}
|
|
95
|
-
function securityDetails(identity) {
|
|
96
|
-
return { requestId: identity.requestId, grantId: identity.grantId, endpoint: identity.identity.endpoint, expiresAt: identity.pendingExpiresAt, activeExpiresAt: identity.activeExpiresAt, permissions: identity.permissions };
|
|
97
|
-
}
|
|
98
|
-
/** Uses the gateway's existing pool; no second connection-string/secret source. */
|
|
99
|
-
export class McpKeyStore {
|
|
100
|
-
pool;
|
|
101
|
-
now;
|
|
102
|
-
config;
|
|
103
|
-
constructor(pool, config, now = Date.now) {
|
|
104
|
-
this.pool = pool;
|
|
105
|
-
this.now = now;
|
|
106
|
-
if (!/^[A-Za-z0-9_-]{1,64}$/.test(config.keyId) || config.key.byteLength !== 32)
|
|
107
|
-
throw new SecurityError('security_setup_required', 'MCP encryption wrapping key and key ID must be provisioned');
|
|
108
|
-
this.config = { keyId: config.keyId, key: Uint8Array.from(config.key) };
|
|
109
|
-
}
|
|
110
|
-
async checkSchema() {
|
|
111
|
-
try {
|
|
112
|
-
await this.pool.query('SELECT owner_id,request_id,grant_id,endpoint_id,envelope,expires_at FROM mcp_endpoint_identities LIMIT 0');
|
|
113
|
-
}
|
|
114
|
-
catch {
|
|
115
|
-
throw new SecurityError('security_setup_required', 'MCP encryption database migration is required');
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
async ensurePendingIdentity(requestId, ownerId, permissions) {
|
|
119
|
-
const existing = await this.pool.query('SELECT * FROM mcp_endpoint_identities WHERE request_id=$1', [requestId]);
|
|
120
|
-
if (existing.rows[0]) {
|
|
121
|
-
const current = await decryptMcpIdentity(dbEnvelope(existing.rows[0]), this.config);
|
|
122
|
-
if (current.ownerId !== ownerId || current.state !== 'pending' || Date.parse(current.pendingExpiresAt) <= this.now() || current.permissions.join(' ') !== permissions.join(' '))
|
|
123
|
-
throw safeUnavailable();
|
|
124
|
-
return securityDetails(current);
|
|
125
|
-
}
|
|
126
|
-
const identity = await generateEndpoint(ownerId, 'mcp', true);
|
|
127
|
-
const privateKey = await crypto.subtle.exportKey('jwk', identity.keyPair.privateKey);
|
|
128
|
-
const record = {
|
|
129
|
-
ownerId, requestId, grantId: b64(randomBytes(32)), identity, bridges: [], permissions,
|
|
130
|
-
pendingExpiresAt: new Date(this.now() + 300_000).toISOString(), activeExpiresAt: new Date(this.now() + MAX_ACTIVE_MS).toISOString(), state: 'pending',
|
|
131
|
-
};
|
|
132
|
-
const envelope = await encryptMcpIdentity(record, privateKey, this.config);
|
|
133
|
-
await this.pool.query('INSERT INTO mcp_endpoint_identities(owner_id,request_id,grant_id,endpoint_id,envelope,expires_at) VALUES($1,$2,$3,$4,$5,$6) ON CONFLICT(request_id) DO NOTHING', [ownerId, requestId, record.grantId, identity.endpoint.id, JSON.stringify(envelope), record.activeExpiresAt]);
|
|
134
|
-
// Reload the winner, including under concurrent consent inspections.
|
|
135
|
-
return this.ensurePendingIdentity(requestId, ownerId, permissions);
|
|
136
|
-
}
|
|
137
|
-
async loadByRequest(ownerId, requestId) {
|
|
138
|
-
const result = await this.pool.query('SELECT * FROM mcp_endpoint_identities WHERE owner_id=$1 AND request_id=$2', [ownerId, requestId]);
|
|
139
|
-
if (!result.rows[0])
|
|
140
|
-
throw safeUnavailable();
|
|
141
|
-
return decryptMcpIdentity(dbEnvelope(result.rows[0]), this.config);
|
|
142
|
-
}
|
|
143
|
-
async loadGrantIdentity(ownerId, grantId) {
|
|
144
|
-
const result = await this.pool.query('SELECT * FROM mcp_endpoint_identities WHERE owner_id=$1 AND grant_id=$2 AND expires_at>NOW()', [ownerId, grantId]);
|
|
145
|
-
if (!result.rows[0])
|
|
146
|
-
throw safeUnavailable();
|
|
147
|
-
const identity = await decryptMcpIdentity(dbEnvelope(result.rows[0]), this.config);
|
|
148
|
-
if ((identity.state !== 'approved' && identity.state !== 'active') || Date.parse(identity.activeExpiresAt) <= this.now())
|
|
149
|
-
throw safeUnavailable();
|
|
150
|
-
if (identity.state === 'approved' && Date.parse(identity.pendingExpiresAt) <= this.now())
|
|
151
|
-
throw safeUnavailable();
|
|
152
|
-
return identity;
|
|
153
|
-
}
|
|
154
|
-
/** Caller must verify exact bridge Auth receipts before supplying these pins. */
|
|
155
|
-
async approve(ownerId, requestId, bridges) {
|
|
156
|
-
if (!bridges.length)
|
|
157
|
-
throw safeUnavailable();
|
|
158
|
-
return this.update(ownerId, requestId, current => {
|
|
159
|
-
if (current.state !== 'pending' || Date.parse(current.pendingExpiresAt) <= this.now()
|
|
160
|
-
|| bridges.some(bridge => bridge.permissions.some(permission => !current.permissions.includes(permission === 'admin' ? 'control' : permission)) || bridge.permissions.includes('admin')))
|
|
161
|
-
throw safeUnavailable();
|
|
162
|
-
return { ...current, state: 'approved', bridges };
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
async markActive(ownerId, requestId) {
|
|
166
|
-
await this.update(ownerId, requestId, current => {
|
|
167
|
-
if (current.state === 'active' && Date.parse(current.activeExpiresAt) > this.now())
|
|
168
|
-
return current;
|
|
169
|
-
if (current.state !== 'approved' || Date.parse(current.pendingExpiresAt) <= this.now())
|
|
170
|
-
throw safeUnavailable();
|
|
171
|
-
return { ...current, state: 'active' };
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
async revoke(ownerId, requestId) {
|
|
175
|
-
await this.update(ownerId, requestId, current => ({ ...current, state: 'revoked' }));
|
|
176
|
-
}
|
|
177
|
-
async update(ownerId, requestId, change) {
|
|
178
|
-
const client = await this.pool.connect();
|
|
179
|
-
try {
|
|
180
|
-
await client.query('BEGIN');
|
|
181
|
-
const result = await client.query('SELECT * FROM mcp_endpoint_identities WHERE owner_id=$1 AND request_id=$2 FOR UPDATE', [ownerId, requestId]);
|
|
182
|
-
if (!result.rows[0])
|
|
183
|
-
throw safeUnavailable();
|
|
184
|
-
const envelope = dbEnvelope(result.rows[0]);
|
|
185
|
-
const current = await decryptMcpIdentity(envelope, this.config);
|
|
186
|
-
const updated = change(current);
|
|
187
|
-
// Private keys are non-extractable after loading. Recover original plaintext only inside the wrapping boundary.
|
|
188
|
-
const key = await configKey(this.config);
|
|
189
|
-
const plain = await crypto.subtle.decrypt({ name: 'AES-GCM', iv: from64(envelope.nonce, 12), additionalData: context(envelope), tagLength: 128 }, key, from64(envelope.ciphertext, 16, MAX_RECORD_BYTES + 16));
|
|
190
|
-
const original = storedSchema.parse(JSON.parse(new TextDecoder().decode(plain)));
|
|
191
|
-
const encrypted = await encryptMcpIdentity(updated, original.privateKey, this.config);
|
|
192
|
-
await client.query('UPDATE mcp_endpoint_identities SET envelope=$1 WHERE owner_id=$2 AND request_id=$3', [JSON.stringify(encrypted), ownerId, requestId]);
|
|
193
|
-
await client.query('COMMIT');
|
|
194
|
-
return updated;
|
|
195
|
-
}
|
|
196
|
-
catch (error) {
|
|
197
|
-
await client.query('ROLLBACK');
|
|
198
|
-
if (error instanceof SecurityError)
|
|
199
|
-
throw error;
|
|
200
|
-
throw safeUnavailable();
|
|
201
|
-
}
|
|
202
|
-
finally {
|
|
203
|
-
client.release();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
//# sourceMappingURL=mcp-key-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-key-store.js","sourceRoot":"","sources":["../../src/mcp/mcp-key-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Pool } from "pg";
|
|
2
|
-
export interface OAuthTransaction {
|
|
3
|
-
get<T>(kind: string, key: string): Promise<T | undefined>;
|
|
4
|
-
put(kind: string, key: string, value: unknown, expiresAt: number): Promise<void>;
|
|
5
|
-
take<T>(kind: string, key: string): Promise<T | undefined>;
|
|
6
|
-
lock(key: string): Promise<void>;
|
|
7
|
-
ownedMachines(subject: string): Promise<string[]>;
|
|
8
|
-
}
|
|
9
|
-
export interface OAuthStore {
|
|
10
|
-
transaction<T>(fn: (tx: OAuthTransaction) => Promise<T>): Promise<T>;
|
|
11
|
-
}
|
|
12
|
-
export declare class PostgresOAuthStore implements OAuthStore {
|
|
13
|
-
readonly pool: Pool;
|
|
14
|
-
private lastPrune;
|
|
15
|
-
constructor(connectionString: string);
|
|
16
|
-
transaction<T>(fn: (tx: OAuthTransaction) => Promise<T>): Promise<T>;
|
|
17
|
-
}
|
package/dist/mcp/oauth-store.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Pool } from "pg";
|
|
2
|
-
class PgTransaction {
|
|
3
|
-
client;
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
async get(kind, key) {
|
|
8
|
-
const result = await this.client.query("SELECT data FROM mcp_oauth_records WHERE kind=$1 AND key=$2 AND expires_at > NOW()", [kind, key]);
|
|
9
|
-
return result.rows[0]?.data;
|
|
10
|
-
}
|
|
11
|
-
async put(kind, key, value, expiresAt) {
|
|
12
|
-
await this.client.query("INSERT INTO mcp_oauth_records(kind,key,data,expires_at) VALUES($1,$2,$3,$4) ON CONFLICT(kind,key) DO UPDATE SET data=EXCLUDED.data,expires_at=EXCLUDED.expires_at", [kind, key, JSON.stringify(value), new Date(expiresAt * 1000)]);
|
|
13
|
-
}
|
|
14
|
-
async take(kind, key) {
|
|
15
|
-
const result = await this.client.query("DELETE FROM mcp_oauth_records WHERE kind=$1 AND key=$2 AND expires_at > NOW() RETURNING data", [kind, key]);
|
|
16
|
-
return result.rows[0]?.data;
|
|
17
|
-
}
|
|
18
|
-
async ownedMachines(subject) {
|
|
19
|
-
const result = await this.client.query("SELECT b.bridge_id FROM bridge_refresh b JOIN users u ON u.email=b.sub WHERE u.id::text=$1 AND b.current_jti <> 'revoked'", [subject]);
|
|
20
|
-
return result.rows.map((r) => r.bridge_id);
|
|
21
|
-
}
|
|
22
|
-
async lock(key) {
|
|
23
|
-
await this.client.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [key]);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
export class PostgresOAuthStore {
|
|
27
|
-
pool;
|
|
28
|
-
lastPrune = 0;
|
|
29
|
-
constructor(connectionString) {
|
|
30
|
-
this.pool = new Pool({
|
|
31
|
-
connectionString,
|
|
32
|
-
max: 10,
|
|
33
|
-
connectionTimeoutMillis: 10000,
|
|
34
|
-
statement_timeout: 10000,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
async transaction(fn) {
|
|
38
|
-
const client = await this.pool.connect();
|
|
39
|
-
try {
|
|
40
|
-
if (Date.now() - this.lastPrune > 60000) {
|
|
41
|
-
this.lastPrune = Date.now();
|
|
42
|
-
await client.query("DELETE FROM mcp_oauth_records WHERE (kind,key) IN (SELECT kind,key FROM mcp_oauth_records WHERE expires_at <= NOW() LIMIT 1000)");
|
|
43
|
-
}
|
|
44
|
-
await client.query("BEGIN");
|
|
45
|
-
const result = await fn(new PgTransaction(client));
|
|
46
|
-
await client.query("COMMIT");
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
catch (e) {
|
|
50
|
-
await client.query("ROLLBACK");
|
|
51
|
-
throw e;
|
|
52
|
-
}
|
|
53
|
-
finally {
|
|
54
|
-
client.release();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
//# sourceMappingURL=oauth-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-store.js","sourceRoot":"","sources":["../../src/mcp/oauth-store.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp/oauth.d.ts
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import type { Response } from "express";
|
|
2
|
-
import type { OAuthServerProvider, AuthorizationParams } from "@modelcontextprotocol/sdk/server/auth/provider.js";
|
|
3
|
-
import type { OAuthClientInformationFull, OAuthTokenRevocationRequest } from "@modelcontextprotocol/sdk/shared/auth.js";
|
|
4
|
-
import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
|
|
5
|
-
import type { OAuthStore } from "./oauth-store.js";
|
|
6
|
-
import type { McpIdentityStore } from './mcp-key-store.js';
|
|
7
|
-
export declare const MCP_SCOPES: string[];
|
|
8
|
-
export interface OAuthOptions {
|
|
9
|
-
publicUrl: string;
|
|
10
|
-
loginUrl: string;
|
|
11
|
-
approvalSecret: string;
|
|
12
|
-
access: Array<{
|
|
13
|
-
subject: string;
|
|
14
|
-
machines: string[];
|
|
15
|
-
}>;
|
|
16
|
-
}
|
|
17
|
-
export declare class FtownOAuthProvider implements OAuthServerProvider {
|
|
18
|
-
readonly store: OAuthStore;
|
|
19
|
-
readonly options: OAuthOptions;
|
|
20
|
-
readonly keys?: McpIdentityStore | undefined;
|
|
21
|
-
readonly resource: string;
|
|
22
|
-
constructor(store: OAuthStore, options: OAuthOptions, keys?: McpIdentityStore | undefined);
|
|
23
|
-
private currentMachines;
|
|
24
|
-
readonly clientsStore: {
|
|
25
|
-
getClient: (id: string) => Promise<{
|
|
26
|
-
redirect_uris: string[];
|
|
27
|
-
client_id: string;
|
|
28
|
-
token_endpoint_auth_method?: string | undefined;
|
|
29
|
-
grant_types?: string[] | undefined;
|
|
30
|
-
response_types?: string[] | undefined;
|
|
31
|
-
client_name?: string | undefined;
|
|
32
|
-
client_uri?: string | undefined;
|
|
33
|
-
logo_uri?: string | undefined;
|
|
34
|
-
scope?: string | undefined;
|
|
35
|
-
contacts?: string[] | undefined;
|
|
36
|
-
tos_uri?: string | undefined;
|
|
37
|
-
policy_uri?: string | undefined;
|
|
38
|
-
jwks_uri?: string | undefined;
|
|
39
|
-
jwks?: any;
|
|
40
|
-
software_id?: string | undefined;
|
|
41
|
-
software_version?: string | undefined;
|
|
42
|
-
software_statement?: string | undefined;
|
|
43
|
-
client_secret?: string | undefined;
|
|
44
|
-
client_id_issued_at?: number | undefined;
|
|
45
|
-
client_secret_expires_at?: number | undefined;
|
|
46
|
-
issuer?: string | undefined;
|
|
47
|
-
} | undefined>;
|
|
48
|
-
registerClient: (input: Omit<OAuthClientInformationFull, "client_id" | "client_id_issued_at">) => Promise<OAuthClientInformationFull>;
|
|
49
|
-
};
|
|
50
|
-
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
|
|
51
|
-
private assertion;
|
|
52
|
-
consentDetails(assertion: string): Promise<{
|
|
53
|
-
clientName: string;
|
|
54
|
-
redirectUri: string;
|
|
55
|
-
scopes: string[];
|
|
56
|
-
machines: string[];
|
|
57
|
-
security: import("../security/protocol.js").McpConsentSecurity;
|
|
58
|
-
}>;
|
|
59
|
-
approve(assertion: string, deny?: boolean): Promise<string>;
|
|
60
|
-
private approvalPins;
|
|
61
|
-
challengeForAuthorizationCode(client: OAuthClientInformationFull, code: string): Promise<string>;
|
|
62
|
-
private tokens;
|
|
63
|
-
exchangeAuthorizationCode(client: OAuthClientInformationFull, code: string, _verifier?: string, redirectUri?: string, resource?: URL): Promise<{
|
|
64
|
-
access_token: string;
|
|
65
|
-
token_type: string;
|
|
66
|
-
id_token?: string | undefined;
|
|
67
|
-
expires_in?: number | undefined;
|
|
68
|
-
scope?: string | undefined;
|
|
69
|
-
refresh_token?: string | undefined;
|
|
70
|
-
issuer?: string | undefined;
|
|
71
|
-
}>;
|
|
72
|
-
exchangeRefreshToken(client: OAuthClientInformationFull, token: string, scopes?: string[], resource?: URL): Promise<{
|
|
73
|
-
access_token: string;
|
|
74
|
-
token_type: string;
|
|
75
|
-
id_token?: string | undefined;
|
|
76
|
-
expires_in?: number | undefined;
|
|
77
|
-
scope?: string | undefined;
|
|
78
|
-
refresh_token?: string | undefined;
|
|
79
|
-
issuer?: string | undefined;
|
|
80
|
-
}>;
|
|
81
|
-
verifyAccessToken(token: string): Promise<AuthInfo>;
|
|
82
|
-
revokeToken(client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
|
|
83
|
-
}
|