deepspace 0.4.4 → 0.4.5
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/cli.js +229 -1306
- package/dist/cli.js.map +1 -1
- package/dist/server.d.ts +2 -86
- package/dist/server.js +9 -495
- package/dist/server.js.map +1 -1
- package/dist/testing.d.ts +115 -0
- package/dist/worker.d.ts +2 -86
- package/dist/worker.js +9 -495
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/server.d.ts
CHANGED
|
@@ -2096,49 +2096,6 @@ declare abstract class CronRoom<E = Record<string, unknown>> extends BaseRoom<E>
|
|
|
2096
2096
|
protected abstract onTask(taskName: string): void | Promise<void>;
|
|
2097
2097
|
}
|
|
2098
2098
|
|
|
2099
|
-
interface SecretMetadata {
|
|
2100
|
-
name: string;
|
|
2101
|
-
version: number;
|
|
2102
|
-
createdAt: string;
|
|
2103
|
-
updatedAt: string;
|
|
2104
|
-
updatedBy: string | null;
|
|
2105
|
-
}
|
|
2106
|
-
declare class SecretsRoom<E extends {
|
|
2107
|
-
APP_SECRETS_KEY?: string;
|
|
2108
|
-
} = {
|
|
2109
|
-
APP_SECRETS_KEY?: string;
|
|
2110
|
-
}> extends BaseRoom<E> {
|
|
2111
|
-
private initialized;
|
|
2112
|
-
protected onMessage(_ws: WebSocket, _user: UserAttachment, _message: {
|
|
2113
|
-
type: string;
|
|
2114
|
-
}): void;
|
|
2115
|
-
fetch(request: Request): Promise<Response>;
|
|
2116
|
-
protected onRequest(request: Request): Promise<Response>;
|
|
2117
|
-
list(): Promise<SecretMetadata[]>;
|
|
2118
|
-
pull(): Promise<Record<string, string>>;
|
|
2119
|
-
patch(body: {
|
|
2120
|
-
set?: Record<string, string>;
|
|
2121
|
-
delete?: string[];
|
|
2122
|
-
updatedBy?: string;
|
|
2123
|
-
}): Promise<{
|
|
2124
|
-
version: number;
|
|
2125
|
-
secrets: SecretMetadata[];
|
|
2126
|
-
}>;
|
|
2127
|
-
replace(body: {
|
|
2128
|
-
secrets?: Record<string, string>;
|
|
2129
|
-
updatedBy?: string;
|
|
2130
|
-
}): Promise<{
|
|
2131
|
-
version: number;
|
|
2132
|
-
secrets: SecretMetadata[];
|
|
2133
|
-
}>;
|
|
2134
|
-
private transaction;
|
|
2135
|
-
private migrateLegacyProductionSecrets;
|
|
2136
|
-
private ensureInitialized;
|
|
2137
|
-
private requireKey;
|
|
2138
|
-
private storeVersion;
|
|
2139
|
-
private bumpStoreVersion;
|
|
2140
|
-
}
|
|
2141
|
-
|
|
2142
2099
|
/**
|
|
2143
2100
|
* JobRoom — Per-app durable background-job execution Durable Object.
|
|
2144
2101
|
*
|
|
@@ -2440,7 +2397,7 @@ declare const ALLOWED_BINDING_TYPES: Set<string>;
|
|
|
2440
2397
|
*
|
|
2441
2398
|
* Includes:
|
|
2442
2399
|
* - Static-asset + service bindings the platform sets up automatically.
|
|
2443
|
-
* - SDK-managed env (auth, identity, owner JWT
|
|
2400
|
+
* - SDK-managed env (auth, identity, owner JWT).
|
|
2444
2401
|
* - The auto-attached cost-tracking AE dataset (`USAGE_EVENTS`).
|
|
2445
2402
|
*
|
|
2446
2403
|
* DO binding names (RECORD_ROOMS, YJS_ROOMS, etc.) are NOT in this set
|
|
@@ -3956,47 +3913,6 @@ declare function createDeepSpaceAuth(config: DeepSpaceAuthConfig): better_auth.A
|
|
|
3956
3913
|
}>;
|
|
3957
3914
|
type DeepSpaceAuth = ReturnType<typeof createDeepSpaceAuth>;
|
|
3958
3915
|
|
|
3959
|
-
interface SecretsEnv {
|
|
3960
|
-
SECRETS_ROOMS?: DurableObjectNamespace;
|
|
3961
|
-
APP_SECRETS_KEY?: string;
|
|
3962
|
-
APP_SECRETS_LOCAL_FALLBACK?: string;
|
|
3963
|
-
}
|
|
3964
|
-
interface SecretRefreshResult {
|
|
3965
|
-
changed: boolean;
|
|
3966
|
-
version: number;
|
|
3967
|
-
}
|
|
3968
|
-
interface WithFreshSecretsContext {
|
|
3969
|
-
secrets: SecretsClient;
|
|
3970
|
-
attempt: number;
|
|
3971
|
-
refreshed: boolean;
|
|
3972
|
-
}
|
|
3973
|
-
interface WithFreshSecretsOptions {
|
|
3974
|
-
/**
|
|
3975
|
-
* By default the operation retries only when a forced refresh observes a
|
|
3976
|
-
* changed secret version after an auth-like failure. Set this for idempotent
|
|
3977
|
-
* operations that should retry after a successful refresh even when the
|
|
3978
|
-
* version is unchanged.
|
|
3979
|
-
*/
|
|
3980
|
-
retryWhenUnchanged?: boolean;
|
|
3981
|
-
}
|
|
3982
|
-
interface SecretsClient {
|
|
3983
|
-
get(name: string): Promise<string | undefined>;
|
|
3984
|
-
require(name: string): Promise<string>;
|
|
3985
|
-
getMany(names: string[]): Promise<Record<string, string | undefined>>;
|
|
3986
|
-
preload(names: string[]): Promise<void>;
|
|
3987
|
-
refresh(options?: {
|
|
3988
|
-
force?: boolean;
|
|
3989
|
-
}): Promise<SecretRefreshResult>;
|
|
3990
|
-
checkForUpdates(): Promise<SecretRefreshResult>;
|
|
3991
|
-
invalidate(): void;
|
|
3992
|
-
withFreshSecrets<T>(operation: (ctx: WithFreshSecretsContext) => Promise<T>, options?: WithFreshSecretsOptions): Promise<T>;
|
|
3993
|
-
}
|
|
3994
|
-
interface CreateSecretsOptions {
|
|
3995
|
-
refreshIntervalMs?: number;
|
|
3996
|
-
now?: () => number;
|
|
3997
|
-
}
|
|
3998
|
-
declare function createSecrets(env: SecretsEnv, options?: CreateSecretsOptions): SecretsClient;
|
|
3999
|
-
|
|
4000
3916
|
/**
|
|
4001
3917
|
* Subscription primitives shared between client (useSubscription hook) and
|
|
4002
3918
|
* server (requireSubscription helper). Pulled into a shared module so the
|
|
@@ -4150,4 +4066,4 @@ declare class RefundError extends Error {
|
|
|
4150
4066
|
constructor(message: string, status: number);
|
|
4151
4067
|
}
|
|
4152
4068
|
|
|
4153
|
-
export { AI_CHATS_SCHEMA, AI_MESSAGES_SCHEMA, ALLOWED_BINDING_TYPES, APP_NAME_RULES, AUTO_PROVISIONABLE_TYPES, AUTO_PROVISION_SENTINEL, type ActionContext, type ActionHandler, type ActionResult, type ActionTools, type ApiWorkerEnv, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CONVERSATION_SCHEMAS, COST_RATES, CancelSubscriptionError, type CancelSubscriptionOpts, type CancelSubscriptionResult, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, type ComposioToolsOptions, type ConvMemberData, type ConvMessageData, type ConvReactionData, type ConvReadCursorData, type ConvVoteData, type ConversationStateData, type
|
|
4069
|
+
export { AI_CHATS_SCHEMA, AI_MESSAGES_SCHEMA, ALLOWED_BINDING_TYPES, APP_NAME_RULES, AUTO_PROVISIONABLE_TYPES, AUTO_PROVISION_SENTINEL, type ActionContext, type ActionHandler, type ActionResult, type ActionTools, type ApiWorkerEnv, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CONVERSATION_SCHEMAS, COST_RATES, CancelSubscriptionError, type CancelSubscriptionOpts, type CancelSubscriptionResult, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, type ComposioToolsOptions, type ConvMemberData, type ConvMessageData, type ConvReactionData, type ConvReadCursorData, type ConvVoteData, type ConversationStateData, type CronContext, type CronExecution, CronRoom, type CronRoomConfig, type CronTask, type CustomBinding, type CustomBindingManifest, DEFAULT_CONTEXT_CONFIG, DEFAULT_DO_MANIFEST, DEFAULT_QUERY_LIMIT, DIRECTORY_SCHEMAS, type DOBindings, type DOManifest, type DOManifestEntry, type DebugApiContext, type DeepSpaceAIEnv, type DeepSpaceAIOptions, type DeepSpaceAuth, type DeepSpaceAuthConfig, type DirectoryCommunityData, type DirectoryConversationData, type DirectoryMembershipData, type DirectoryPostData, type DoMigrationDirective, type DoMigrationPlan, type ExistingDOBinding, GLOBAL_DO_TYPES, GLOBAL_DO_TYPE_NAMES, type GameInput, GameRoom, type GameRoomConfig, type GetActionData, type GlobalDOType, type Job, type JobContext, JobRoom, type JobRoomConfig, type JobStatus, type JwtClaims, type JwtVerifierConfig, MESSAGES_SCHEMA, type MutateActionData, type PermissionAnalysis, type PermissionContext, type PermissionLevel, type PermissionSource, type PlanInfo, type PlatformWorkerEnv, type Player, type PrefixResult, type PresencePeer, PresenceRoom, type QueryActionData, REACTIONS_SCHEMA, READ_RECEIPTS_SCHEMA, RESERVED_BINDING_NAMES, RESERVED_COLLECTION_NAMES, type RecordContext, RecordRoom, type RecordRoomConfig, RefundError, type RefundOpts, type RefundResult, type ResolvedColumn, type ResolvedPermission, type RolePermissions, type RunMigrationsResult, SYSTEM_COLLECTION_SCHEMAS, SYSTEM_MANAGED_COLUMNS, SchemaRegistry, type ScopeContext, type ScopedR2Auth, type ScopedR2Config, type ScopedR2Handler, type ScreenshotEnv, type ScreenshotOptions, type ScreenshotResult, type SharedConnection, type StoredRecord, SubscriptionAuthError, type SubscriptionContext, type SubscriptionRead, SubscriptionRequiredError, type SubscriptionStatus, type Summarizer, type TokenDebugInfo, type ToolResult, type ToolSchema, type ToolsApiContext, USERS_COLUMNS, type User, type UserAttachment, type UserContext, VOTING_SCHEMAS, type ValidationError, type VerifiedAuth, type VerifyOutcome, type VerifyResult, type Viewport, WORKSPACE_SCHEMAS, type YjsContext, YjsRoom, analyzePermissions, apiWorkerFetch, appendMessage, applyAiToolDefaults, applySlidingWindow, authWorkerFetch, bindingManifestFromOutputConfig, broadcastChange, broadcastYjsUpdate, buildCronContext, buildTableSelect, buildUiParts, canCreate, canDelete, canRead, canUpdate, cancelSubscription, capToolResultSize, captureScreenshot, checkFieldPermissions, coerceValue, collectionTableName, columnId, composioTools, computeDoMigration, computeHmacHex, createChat, createDeepSpaceAI, createDeepSpaceAuth, createScopedR2Handler, dataToColumnValues, decodeJwtPayload, deleteChatCascade, deleteRecord, enqueueJob, executeQuery, getAllUsers, getChat, getGlobalDOSchemas, getGlobalDOType, getOrCreateYjsDoc, getRecord, getRolePermissions, getSubscription, getUser, getYjsDocKey, handleApiRequest, handleDelete, handlePut, handleSetRole, handleSubscribe, handleToolsRequest, handleUnsubscribe, handleUserList, handleUserUpdate, handleYjsBinaryMessage, handleYjsJoin, handleYjsLeave, isAutoProvision, isOwner, lintSchema, loadMessages, makeDefaultSummarizer, meterAi, meterUsage, meterVectorize, noopPermissionContext, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, putRecord, readRecord, recordMatchesSubscription, refundInvoice, registerUser, requireSubscription, resolveAppName, resolveColumn, rowToData, runMigrations, saveYjsDoc, timingSafeEqualHex, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema };
|
package/dist/server.js
CHANGED
|
@@ -3978,13 +3978,13 @@ var YjsRoom = class extends BaseRoom {
|
|
|
3978
3978
|
onMessage(ws, user, message) {
|
|
3979
3979
|
}
|
|
3980
3980
|
onBinaryMessage(ws, user, data) {
|
|
3981
|
-
const
|
|
3982
|
-
const decoder = createDecoder(
|
|
3981
|
+
const bytes = new Uint8Array(data);
|
|
3982
|
+
const decoder = createDecoder(bytes);
|
|
3983
3983
|
const messageType = readVarUint(decoder);
|
|
3984
3984
|
if (messageType === MSG_SYNC) {
|
|
3985
|
-
this.handleSync(ws, decoder,
|
|
3985
|
+
this.handleSync(ws, decoder, bytes);
|
|
3986
3986
|
} else if (messageType === MSG_AWARENESS) {
|
|
3987
|
-
this.handleAwareness(ws, decoder,
|
|
3987
|
+
this.handleAwareness(ws, decoder, bytes);
|
|
3988
3988
|
}
|
|
3989
3989
|
}
|
|
3990
3990
|
onDisconnect(ws, user) {
|
|
@@ -5189,319 +5189,6 @@ function cronMatches(parsed, timezone, date) {
|
|
|
5189
5189
|
return parsed.minute.has(minute) && parsed.hour.has(hour) && parsed.dayOfMonth.has(dayOfMonth) && parsed.month.has(month) && parsed.dayOfWeek.has(dayOfWeek);
|
|
5190
5190
|
}
|
|
5191
5191
|
|
|
5192
|
-
// src/server/rooms/secrets-room.ts
|
|
5193
|
-
var INTERNAL_HEADER = "x-deepspace-internal";
|
|
5194
|
-
var INTERNAL_VALUE = "app-secrets";
|
|
5195
|
-
var VERSION = "app-secret-v1";
|
|
5196
|
-
var NAME_INFO = "deepspace app secret name v1";
|
|
5197
|
-
var VALUE_INFO = "deepspace app secret value v1";
|
|
5198
|
-
var HMAC_INFO = "deepspace app secret lookup v1";
|
|
5199
|
-
var STORE_ID = "default";
|
|
5200
|
-
var SecretsRoom = class extends BaseRoom {
|
|
5201
|
-
initialized = false;
|
|
5202
|
-
onMessage(_ws, _user, _message) {
|
|
5203
|
-
}
|
|
5204
|
-
async fetch(request) {
|
|
5205
|
-
this.ensureInitialized();
|
|
5206
|
-
return super.fetch(request);
|
|
5207
|
-
}
|
|
5208
|
-
async onRequest(request) {
|
|
5209
|
-
if (request.headers.get(INTERNAL_HEADER) !== INTERNAL_VALUE) {
|
|
5210
|
-
return json({ error: "Not found" }, 404);
|
|
5211
|
-
}
|
|
5212
|
-
const url = new URL(request.url);
|
|
5213
|
-
try {
|
|
5214
|
-
if (request.method === "GET" && url.pathname.endsWith("/list")) {
|
|
5215
|
-
return json({ version: this.storeVersion(), secrets: await this.list() });
|
|
5216
|
-
}
|
|
5217
|
-
if (request.method === "GET" && url.pathname.endsWith("/pull")) {
|
|
5218
|
-
return json({ version: this.storeVersion(), secrets: await this.pull() });
|
|
5219
|
-
}
|
|
5220
|
-
if (request.method === "GET" && url.pathname.endsWith("/version")) {
|
|
5221
|
-
return json({ version: this.storeVersion() });
|
|
5222
|
-
}
|
|
5223
|
-
if (request.method === "PATCH" && url.pathname.endsWith("/patch")) {
|
|
5224
|
-
const body = await request.json();
|
|
5225
|
-
const result = await this.patch(body);
|
|
5226
|
-
return json(result);
|
|
5227
|
-
}
|
|
5228
|
-
if (request.method === "PUT" && url.pathname.endsWith("/replace")) {
|
|
5229
|
-
const body = await request.json();
|
|
5230
|
-
const result = await this.replace(body);
|
|
5231
|
-
return json(result);
|
|
5232
|
-
}
|
|
5233
|
-
} catch (err) {
|
|
5234
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
5235
|
-
const status = message.includes("conflict") ? 409 : 500;
|
|
5236
|
-
return json({ error: message }, status);
|
|
5237
|
-
}
|
|
5238
|
-
return json({ error: "Not found" }, 404);
|
|
5239
|
-
}
|
|
5240
|
-
async list() {
|
|
5241
|
-
const rows = this.sql.exec(
|
|
5242
|
-
`SELECT name_encrypted, version, updated_by, created_at, updated_at
|
|
5243
|
-
FROM app_secrets_store ORDER BY updated_at DESC`
|
|
5244
|
-
).toArray();
|
|
5245
|
-
const out = [];
|
|
5246
|
-
for (const row of rows) {
|
|
5247
|
-
out.push({
|
|
5248
|
-
name: await decryptText(this.requireKey(), row.name_encrypted, NAME_INFO),
|
|
5249
|
-
version: row.version,
|
|
5250
|
-
createdAt: row.created_at,
|
|
5251
|
-
updatedAt: row.updated_at,
|
|
5252
|
-
updatedBy: row.updated_by
|
|
5253
|
-
});
|
|
5254
|
-
}
|
|
5255
|
-
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
5256
|
-
}
|
|
5257
|
-
async pull() {
|
|
5258
|
-
const rows = this.sql.exec(
|
|
5259
|
-
`SELECT name_hash, name_encrypted, value_encrypted, version, updated_by, created_at, updated_at
|
|
5260
|
-
FROM app_secrets_store`
|
|
5261
|
-
).toArray();
|
|
5262
|
-
const out = {};
|
|
5263
|
-
for (const row of rows) {
|
|
5264
|
-
const name = await decryptText(this.requireKey(), row.name_encrypted, NAME_INFO);
|
|
5265
|
-
out[name] = await decryptText(this.requireKey(), row.value_encrypted, VALUE_INFO);
|
|
5266
|
-
}
|
|
5267
|
-
return out;
|
|
5268
|
-
}
|
|
5269
|
-
async patch(body) {
|
|
5270
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5271
|
-
const actor = body.updatedBy ?? null;
|
|
5272
|
-
const key = this.requireKey();
|
|
5273
|
-
const setEntries = Object.entries(body.set ?? {});
|
|
5274
|
-
const deleteNames = body.delete ?? [];
|
|
5275
|
-
for (const name of [...setEntries.map(([name2]) => name2), ...deleteNames]) {
|
|
5276
|
-
validateSecretName(name);
|
|
5277
|
-
}
|
|
5278
|
-
const writes = [];
|
|
5279
|
-
for (const [name, value] of setEntries) {
|
|
5280
|
-
const nameHash = await hashName(key, name);
|
|
5281
|
-
const existing = this.sql.exec(
|
|
5282
|
-
`SELECT version, created_at FROM app_secrets_store WHERE name_hash = ?`,
|
|
5283
|
-
nameHash
|
|
5284
|
-
).toArray()[0];
|
|
5285
|
-
writes.push({
|
|
5286
|
-
nameHash,
|
|
5287
|
-
nameEncrypted: await encryptText(key, name, NAME_INFO),
|
|
5288
|
-
valueEncrypted: await encryptText(key, value, VALUE_INFO),
|
|
5289
|
-
version: (existing?.version ?? 0) + 1,
|
|
5290
|
-
createdAt: existing?.created_at ?? now
|
|
5291
|
-
});
|
|
5292
|
-
}
|
|
5293
|
-
const deletes = [];
|
|
5294
|
-
for (const name of deleteNames) {
|
|
5295
|
-
deletes.push(await hashName(key, name));
|
|
5296
|
-
}
|
|
5297
|
-
this.transaction(() => {
|
|
5298
|
-
for (const write of writes) {
|
|
5299
|
-
this.sql.exec(
|
|
5300
|
-
`INSERT OR REPLACE INTO app_secrets_store
|
|
5301
|
-
(name_hash, name_encrypted, value_encrypted, version, updated_by, created_at, updated_at)
|
|
5302
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
5303
|
-
write.nameHash,
|
|
5304
|
-
write.nameEncrypted,
|
|
5305
|
-
write.valueEncrypted,
|
|
5306
|
-
write.version,
|
|
5307
|
-
actor,
|
|
5308
|
-
write.createdAt,
|
|
5309
|
-
now
|
|
5310
|
-
);
|
|
5311
|
-
}
|
|
5312
|
-
for (const nameHash of deletes) {
|
|
5313
|
-
this.sql.exec(`DELETE FROM app_secrets_store WHERE name_hash = ?`, nameHash);
|
|
5314
|
-
}
|
|
5315
|
-
this.bumpStoreVersion(now);
|
|
5316
|
-
});
|
|
5317
|
-
return { version: this.storeVersion(), secrets: await this.list() };
|
|
5318
|
-
}
|
|
5319
|
-
async replace(body) {
|
|
5320
|
-
const next = body.secrets ?? {};
|
|
5321
|
-
for (const name of Object.keys(next)) validateSecretName(name);
|
|
5322
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5323
|
-
const actor = body.updatedBy ?? null;
|
|
5324
|
-
const key = this.requireKey();
|
|
5325
|
-
const writes = [];
|
|
5326
|
-
for (const [name, value] of Object.entries(next)) {
|
|
5327
|
-
writes.push({
|
|
5328
|
-
nameHash: await hashName(key, name),
|
|
5329
|
-
nameEncrypted: await encryptText(key, name, NAME_INFO),
|
|
5330
|
-
valueEncrypted: await encryptText(key, value, VALUE_INFO)
|
|
5331
|
-
});
|
|
5332
|
-
}
|
|
5333
|
-
this.transaction(() => {
|
|
5334
|
-
this.sql.exec(`DELETE FROM app_secrets_store`);
|
|
5335
|
-
for (const write of writes) {
|
|
5336
|
-
this.sql.exec(
|
|
5337
|
-
`INSERT INTO app_secrets_store
|
|
5338
|
-
(name_hash, name_encrypted, value_encrypted, version, updated_by, created_at, updated_at)
|
|
5339
|
-
VALUES (?, ?, ?, 1, ?, ?, ?)`,
|
|
5340
|
-
write.nameHash,
|
|
5341
|
-
write.nameEncrypted,
|
|
5342
|
-
write.valueEncrypted,
|
|
5343
|
-
actor,
|
|
5344
|
-
now,
|
|
5345
|
-
now
|
|
5346
|
-
);
|
|
5347
|
-
}
|
|
5348
|
-
this.bumpStoreVersion(now);
|
|
5349
|
-
});
|
|
5350
|
-
return { version: this.storeVersion(), secrets: await this.list() };
|
|
5351
|
-
}
|
|
5352
|
-
transaction(run) {
|
|
5353
|
-
this.state.storage.transactionSync(run);
|
|
5354
|
-
}
|
|
5355
|
-
migrateLegacyProductionSecrets() {
|
|
5356
|
-
const legacyExists = this.sql.exec(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'app_secrets'`).toArray().length > 0;
|
|
5357
|
-
if (!legacyExists) return;
|
|
5358
|
-
const currentCount = this.sql.exec(`SELECT COUNT(*) AS count FROM app_secrets_store`).toArray()[0];
|
|
5359
|
-
if ((currentCount?.count ?? 0) > 0) return;
|
|
5360
|
-
this.sql.exec(`
|
|
5361
|
-
INSERT OR IGNORE INTO app_secrets_store
|
|
5362
|
-
(name_hash, name_encrypted, value_encrypted, version, updated_by, created_at, updated_at)
|
|
5363
|
-
SELECT name_hash, name_encrypted, value_encrypted, version, updated_by, created_at, updated_at
|
|
5364
|
-
FROM app_secrets
|
|
5365
|
-
WHERE env = 'production'
|
|
5366
|
-
`);
|
|
5367
|
-
const legacyVersionExists = this.sql.exec(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'app_secret_env_versions'`).toArray().length > 0;
|
|
5368
|
-
const legacyVersion = legacyVersionExists ? this.sql.exec(`SELECT version, updated_at FROM app_secret_env_versions WHERE env = 'production'`).toArray()[0] : void 0;
|
|
5369
|
-
if (legacyVersion) {
|
|
5370
|
-
this.sql.exec(
|
|
5371
|
-
`INSERT OR REPLACE INTO app_secret_store_versions (id, version, updated_at) VALUES (?, ?, ?)`,
|
|
5372
|
-
STORE_ID,
|
|
5373
|
-
legacyVersion.version,
|
|
5374
|
-
legacyVersion.updated_at
|
|
5375
|
-
);
|
|
5376
|
-
}
|
|
5377
|
-
const migratedCount = this.sql.exec(`SELECT COUNT(*) AS count FROM app_secrets_store`).toArray()[0];
|
|
5378
|
-
if (!legacyVersion && (migratedCount?.count ?? 0) > 0) {
|
|
5379
|
-
this.sql.exec(
|
|
5380
|
-
`INSERT OR REPLACE INTO app_secret_store_versions (id, version, updated_at) VALUES (?, ?, ?)`,
|
|
5381
|
-
STORE_ID,
|
|
5382
|
-
1,
|
|
5383
|
-
(/* @__PURE__ */ new Date()).toISOString()
|
|
5384
|
-
);
|
|
5385
|
-
}
|
|
5386
|
-
}
|
|
5387
|
-
ensureInitialized() {
|
|
5388
|
-
if (this.initialized) return;
|
|
5389
|
-
this.initialized = true;
|
|
5390
|
-
this.sql.exec(`
|
|
5391
|
-
CREATE TABLE IF NOT EXISTS app_secrets_store (
|
|
5392
|
-
name_hash TEXT NOT NULL,
|
|
5393
|
-
name_encrypted TEXT NOT NULL,
|
|
5394
|
-
value_encrypted TEXT NOT NULL,
|
|
5395
|
-
version INTEGER NOT NULL,
|
|
5396
|
-
updated_by TEXT,
|
|
5397
|
-
created_at TEXT NOT NULL,
|
|
5398
|
-
updated_at TEXT NOT NULL,
|
|
5399
|
-
PRIMARY KEY (name_hash)
|
|
5400
|
-
)
|
|
5401
|
-
`);
|
|
5402
|
-
this.sql.exec(`
|
|
5403
|
-
CREATE TABLE IF NOT EXISTS app_secret_store_versions (
|
|
5404
|
-
id TEXT PRIMARY KEY,
|
|
5405
|
-
version INTEGER NOT NULL,
|
|
5406
|
-
updated_at TEXT NOT NULL
|
|
5407
|
-
)
|
|
5408
|
-
`);
|
|
5409
|
-
this.migrateLegacyProductionSecrets();
|
|
5410
|
-
}
|
|
5411
|
-
requireKey() {
|
|
5412
|
-
if (!this.env.APP_SECRETS_KEY) {
|
|
5413
|
-
throw new Error("APP_SECRETS_KEY binding is missing");
|
|
5414
|
-
}
|
|
5415
|
-
return this.env.APP_SECRETS_KEY;
|
|
5416
|
-
}
|
|
5417
|
-
storeVersion() {
|
|
5418
|
-
const row = this.sql.exec(
|
|
5419
|
-
`SELECT version FROM app_secret_store_versions WHERE id = ?`,
|
|
5420
|
-
STORE_ID
|
|
5421
|
-
).toArray()[0];
|
|
5422
|
-
return row?.version ?? 0;
|
|
5423
|
-
}
|
|
5424
|
-
bumpStoreVersion(now) {
|
|
5425
|
-
const next = this.storeVersion() + 1;
|
|
5426
|
-
this.sql.exec(
|
|
5427
|
-
`INSERT OR REPLACE INTO app_secret_store_versions (id, version, updated_at) VALUES (?, ?, ?)`,
|
|
5428
|
-
STORE_ID,
|
|
5429
|
-
next,
|
|
5430
|
-
now
|
|
5431
|
-
);
|
|
5432
|
-
}
|
|
5433
|
-
};
|
|
5434
|
-
function validateSecretName(name) {
|
|
5435
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
|
|
5436
|
-
throw new Error(`Invalid secret name "${name}"`);
|
|
5437
|
-
}
|
|
5438
|
-
}
|
|
5439
|
-
function json(body, status = 200) {
|
|
5440
|
-
return new Response(JSON.stringify(body), {
|
|
5441
|
-
status,
|
|
5442
|
-
headers: { "Content-Type": "application/json" }
|
|
5443
|
-
});
|
|
5444
|
-
}
|
|
5445
|
-
async function encryptText(root, plaintext, info) {
|
|
5446
|
-
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
5447
|
-
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
5448
|
-
const key = await aesKey(root, salt, info);
|
|
5449
|
-
const ciphertext = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, new TextEncoder().encode(plaintext));
|
|
5450
|
-
return [VERSION, b64(salt), b64(iv), b64(new Uint8Array(ciphertext))].join(":");
|
|
5451
|
-
}
|
|
5452
|
-
async function decryptText(root, encoded, info) {
|
|
5453
|
-
const [version, saltB64, ivB64, bodyB64] = encoded.split(":");
|
|
5454
|
-
if (version !== VERSION || !saltB64 || !ivB64 || !bodyB64) {
|
|
5455
|
-
throw new Error("Corrupt app secret ciphertext");
|
|
5456
|
-
}
|
|
5457
|
-
const key = await aesKey(root, unb64(saltB64), info);
|
|
5458
|
-
const plaintext = await crypto.subtle.decrypt(
|
|
5459
|
-
{ name: "AES-GCM", iv: bytes(unb64(ivB64)) },
|
|
5460
|
-
key,
|
|
5461
|
-
bytes(unb64(bodyB64))
|
|
5462
|
-
);
|
|
5463
|
-
return new TextDecoder().decode(plaintext);
|
|
5464
|
-
}
|
|
5465
|
-
async function hashName(root, name) {
|
|
5466
|
-
const key = await hmacKey(root, HMAC_INFO);
|
|
5467
|
-
const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`production:${name}`));
|
|
5468
|
-
return Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
5469
|
-
}
|
|
5470
|
-
async function aesKey(root, salt, info) {
|
|
5471
|
-
const base = await crypto.subtle.importKey("raw", new TextEncoder().encode(root), "HKDF", false, ["deriveKey"]);
|
|
5472
|
-
return crypto.subtle.deriveKey(
|
|
5473
|
-
{ name: "HKDF", hash: "SHA-256", salt: bytes(salt), info: new TextEncoder().encode(info) },
|
|
5474
|
-
base,
|
|
5475
|
-
{ name: "AES-GCM", length: 256 },
|
|
5476
|
-
false,
|
|
5477
|
-
["encrypt", "decrypt"]
|
|
5478
|
-
);
|
|
5479
|
-
}
|
|
5480
|
-
async function hmacKey(root, info) {
|
|
5481
|
-
const base = await crypto.subtle.importKey("raw", new TextEncoder().encode(root), "HKDF", false, ["deriveKey"]);
|
|
5482
|
-
return crypto.subtle.deriveKey(
|
|
5483
|
-
{ name: "HKDF", hash: "SHA-256", salt: bytes(new Uint8Array(16)), info: new TextEncoder().encode(info) },
|
|
5484
|
-
base,
|
|
5485
|
-
{ name: "HMAC", hash: "SHA-256", length: 256 },
|
|
5486
|
-
false,
|
|
5487
|
-
["sign"]
|
|
5488
|
-
);
|
|
5489
|
-
}
|
|
5490
|
-
function b64(bytes2) {
|
|
5491
|
-
let s = "";
|
|
5492
|
-
for (const b of bytes2) s += String.fromCharCode(b);
|
|
5493
|
-
return btoa(s);
|
|
5494
|
-
}
|
|
5495
|
-
function unb64(value) {
|
|
5496
|
-
const s = atob(value);
|
|
5497
|
-
const out = new Uint8Array(s.length);
|
|
5498
|
-
for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
|
|
5499
|
-
return out;
|
|
5500
|
-
}
|
|
5501
|
-
function bytes(input) {
|
|
5502
|
-
return input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength);
|
|
5503
|
-
}
|
|
5504
|
-
|
|
5505
5192
|
// src/server/rooms/job-room.ts
|
|
5506
5193
|
var RUNNING_STALE_MS = 16 * 60 * 1e3;
|
|
5507
5194
|
var DEFAULT_RETENTION_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -6119,7 +5806,6 @@ var RESERVED_BINDING_NAMES = /* @__PURE__ */ new Set([
|
|
|
6119
5806
|
"AUTH_WORKER_URL",
|
|
6120
5807
|
"APP_IDENTITY_TOKEN",
|
|
6121
5808
|
"APP_OWNER_JWT",
|
|
6122
|
-
"APP_SECRETS_KEY",
|
|
6123
5809
|
"USAGE_EVENTS"
|
|
6124
5810
|
]);
|
|
6125
5811
|
function validateBindingManifest(manifest) {
|
|
@@ -6956,8 +6642,8 @@ import { importSPKI, jwtVerify } from "jose";
|
|
|
6956
6642
|
|
|
6957
6643
|
// src/server/auth/utils.ts
|
|
6958
6644
|
var BASE64_URL_REGEX = /^[A-Za-z0-9-_]+$/;
|
|
6959
|
-
function bufferToHex(
|
|
6960
|
-
const view =
|
|
6645
|
+
function bufferToHex(bytes) {
|
|
6646
|
+
const view = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
6961
6647
|
let hex = "";
|
|
6962
6648
|
for (const byte of view) {
|
|
6963
6649
|
hex += byte.toString(16).padStart(2, "0");
|
|
@@ -6980,9 +6666,9 @@ function decodeJwtPayload(token) {
|
|
|
6980
6666
|
if (!BASE64_URL_REGEX.test(payloadSegment)) return void 0;
|
|
6981
6667
|
try {
|
|
6982
6668
|
const normalized = payloadSegment.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(payloadSegment.length / 4) * 4, "=");
|
|
6983
|
-
const
|
|
6984
|
-
const
|
|
6985
|
-
const payload = JSON.parse(
|
|
6669
|
+
const bytes = base64ToUint8Array(normalized);
|
|
6670
|
+
const json = new TextDecoder().decode(bytes);
|
|
6671
|
+
const payload = JSON.parse(json);
|
|
6986
6672
|
return {
|
|
6987
6673
|
iss: payload.iss ?? null,
|
|
6988
6674
|
aud: payload.aud ?? null,
|
|
@@ -7206,176 +6892,6 @@ async function generateAppleClientSecret(apple) {
|
|
|
7206
6892
|
return token;
|
|
7207
6893
|
}
|
|
7208
6894
|
|
|
7209
|
-
// src/server/secrets.ts
|
|
7210
|
-
var DEFAULT_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
7211
|
-
function createSecrets(env, options = {}) {
|
|
7212
|
-
const refreshIntervalMs = options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS;
|
|
7213
|
-
const now = options.now ?? (() => Date.now());
|
|
7214
|
-
const cache = /* @__PURE__ */ new Map();
|
|
7215
|
-
let loadedAll = null;
|
|
7216
|
-
let loadedVersion = 0;
|
|
7217
|
-
let lastCheckedAt = 0;
|
|
7218
|
-
function stub() {
|
|
7219
|
-
if (!env.SECRETS_ROOMS) throw new Error("SECRETS_ROOMS binding is missing");
|
|
7220
|
-
if (!env.APP_SECRETS_KEY) throw new Error("APP_SECRETS_KEY binding is missing");
|
|
7221
|
-
const id = env.SECRETS_ROOMS.idFromName("app-secrets");
|
|
7222
|
-
return env.SECRETS_ROOMS.get(id);
|
|
7223
|
-
}
|
|
7224
|
-
async function fetchJson(path) {
|
|
7225
|
-
const res = await stub().fetch(`https://app-secrets/${path}`, {
|
|
7226
|
-
headers: { "x-deepspace-internal": "app-secrets" }
|
|
7227
|
-
});
|
|
7228
|
-
const body = await res.json().catch(() => ({}));
|
|
7229
|
-
if (!res.ok) throw new Error(body.error ?? `App secrets unavailable (${res.status})`);
|
|
7230
|
-
return body;
|
|
7231
|
-
}
|
|
7232
|
-
async function pullAll() {
|
|
7233
|
-
const body = await fetchJson("pull");
|
|
7234
|
-
const version = typeof body.version === "number" ? body.version : 0;
|
|
7235
|
-
cache.clear();
|
|
7236
|
-
for (const [name, value] of Object.entries(body.secrets ?? {})) {
|
|
7237
|
-
cache.set(name, value);
|
|
7238
|
-
}
|
|
7239
|
-
loadedVersion = version;
|
|
7240
|
-
lastCheckedAt = now();
|
|
7241
|
-
return version;
|
|
7242
|
-
}
|
|
7243
|
-
async function loadAll() {
|
|
7244
|
-
await pullAll();
|
|
7245
|
-
}
|
|
7246
|
-
async function ensureLoaded() {
|
|
7247
|
-
if (!loadedAll) {
|
|
7248
|
-
loadedAll = loadAll().catch((err) => {
|
|
7249
|
-
loadedAll = null;
|
|
7250
|
-
throw err;
|
|
7251
|
-
});
|
|
7252
|
-
}
|
|
7253
|
-
await loadedAll;
|
|
7254
|
-
}
|
|
7255
|
-
async function maybeCheckForUpdates() {
|
|
7256
|
-
if (!loadedAll) return;
|
|
7257
|
-
if (refreshIntervalMs < 0) return;
|
|
7258
|
-
if (now() - lastCheckedAt < refreshIntervalMs) return;
|
|
7259
|
-
try {
|
|
7260
|
-
await client.checkForUpdates();
|
|
7261
|
-
} catch {
|
|
7262
|
-
}
|
|
7263
|
-
}
|
|
7264
|
-
function localDevValue(name) {
|
|
7265
|
-
const value = env[name];
|
|
7266
|
-
return env.APP_SECRETS_LOCAL_FALLBACK === "true" && typeof value === "string" ? value : void 0;
|
|
7267
|
-
}
|
|
7268
|
-
const client = {
|
|
7269
|
-
async get(name) {
|
|
7270
|
-
const local = localDevValue(name);
|
|
7271
|
-
if (local !== void 0) return local;
|
|
7272
|
-
if (!cache.has(name)) await ensureLoaded();
|
|
7273
|
-
else await maybeCheckForUpdates();
|
|
7274
|
-
return cache.get(name);
|
|
7275
|
-
},
|
|
7276
|
-
async require(name) {
|
|
7277
|
-
const value = await this.get(name);
|
|
7278
|
-
if (value === void 0) throw new Error(`Missing app secret "${name}"`);
|
|
7279
|
-
return value;
|
|
7280
|
-
},
|
|
7281
|
-
async getMany(names) {
|
|
7282
|
-
const out = {};
|
|
7283
|
-
for (const name of names) out[name] = await this.get(name);
|
|
7284
|
-
return out;
|
|
7285
|
-
},
|
|
7286
|
-
async preload(names) {
|
|
7287
|
-
if (env.APP_SECRETS_LOCAL_FALLBACK === "true") {
|
|
7288
|
-
const missing = [];
|
|
7289
|
-
for (const name of names) {
|
|
7290
|
-
const local = localDevValue(name);
|
|
7291
|
-
if (local !== void 0) cache.set(name, local);
|
|
7292
|
-
else missing.push(name);
|
|
7293
|
-
}
|
|
7294
|
-
if (missing.length === 0) {
|
|
7295
|
-
await maybeCheckForUpdates();
|
|
7296
|
-
return;
|
|
7297
|
-
}
|
|
7298
|
-
}
|
|
7299
|
-
await ensureLoaded();
|
|
7300
|
-
await maybeCheckForUpdates();
|
|
7301
|
-
},
|
|
7302
|
-
async refresh(refreshOptions = {}) {
|
|
7303
|
-
if (refreshOptions.force || !loadedAll) {
|
|
7304
|
-
const previous = loadedVersion;
|
|
7305
|
-
const version = await pullAll();
|
|
7306
|
-
loadedAll = Promise.resolve();
|
|
7307
|
-
return { changed: version !== previous, version };
|
|
7308
|
-
}
|
|
7309
|
-
return this.checkForUpdates();
|
|
7310
|
-
},
|
|
7311
|
-
async checkForUpdates() {
|
|
7312
|
-
await ensureLoaded();
|
|
7313
|
-
const body = await fetchJson("version");
|
|
7314
|
-
const version = typeof body.version === "number" ? body.version : 0;
|
|
7315
|
-
lastCheckedAt = now();
|
|
7316
|
-
if (version === loadedVersion) return { changed: false, version };
|
|
7317
|
-
const pulledVersion = await pullAll();
|
|
7318
|
-
return { changed: true, version: pulledVersion };
|
|
7319
|
-
},
|
|
7320
|
-
invalidate() {
|
|
7321
|
-
cache.clear();
|
|
7322
|
-
loadedAll = null;
|
|
7323
|
-
loadedVersion = 0;
|
|
7324
|
-
lastCheckedAt = 0;
|
|
7325
|
-
},
|
|
7326
|
-
async withFreshSecrets(operation, retryOptions = {}) {
|
|
7327
|
-
let first;
|
|
7328
|
-
try {
|
|
7329
|
-
first = await operation({ secrets: client, attempt: 1, refreshed: false });
|
|
7330
|
-
} catch (err) {
|
|
7331
|
-
if (!shouldRefreshOnError(err)) throw err;
|
|
7332
|
-
const refresh = await refreshAfterFailure(err);
|
|
7333
|
-
if (!refresh.changed && !retryOptions.retryWhenUnchanged) throw err;
|
|
7334
|
-
return operation({ secrets: client, attempt: 2, refreshed: refresh.changed });
|
|
7335
|
-
}
|
|
7336
|
-
if (first instanceof Response && shouldRefreshOnStatus(first.status)) {
|
|
7337
|
-
const refresh = await refreshAfterFailure(first);
|
|
7338
|
-
if (refresh.changed || retryOptions.retryWhenUnchanged) {
|
|
7339
|
-
return operation({ secrets: client, attempt: 2, refreshed: refresh.changed });
|
|
7340
|
-
}
|
|
7341
|
-
}
|
|
7342
|
-
return first;
|
|
7343
|
-
}
|
|
7344
|
-
};
|
|
7345
|
-
async function refreshAfterFailure(original) {
|
|
7346
|
-
try {
|
|
7347
|
-
return await client.refresh({ force: true });
|
|
7348
|
-
} catch (err) {
|
|
7349
|
-
const originalMessage = describeFailure(original);
|
|
7350
|
-
const refreshMessage = err instanceof Error ? err.message : String(err);
|
|
7351
|
-
throw new Error(`Secret refresh failed after API failure (${originalMessage}): ${refreshMessage}`);
|
|
7352
|
-
}
|
|
7353
|
-
}
|
|
7354
|
-
return client;
|
|
7355
|
-
}
|
|
7356
|
-
function shouldRefreshOnError(error) {
|
|
7357
|
-
const status = statusFromError(error);
|
|
7358
|
-
return status !== void 0 && shouldRefreshOnStatus(status);
|
|
7359
|
-
}
|
|
7360
|
-
function shouldRefreshOnStatus(status) {
|
|
7361
|
-
return status === 401 || status === 403;
|
|
7362
|
-
}
|
|
7363
|
-
function statusFromError(error) {
|
|
7364
|
-
if (!error || typeof error !== "object") return void 0;
|
|
7365
|
-
const record = error;
|
|
7366
|
-
if (typeof record.status === "number") return record.status;
|
|
7367
|
-
if (typeof record.statusCode === "number") return record.statusCode;
|
|
7368
|
-
if (typeof record.response?.status === "number") return record.response.status;
|
|
7369
|
-
return void 0;
|
|
7370
|
-
}
|
|
7371
|
-
function describeFailure(value) {
|
|
7372
|
-
if (value instanceof Response) return `HTTP ${value.status}`;
|
|
7373
|
-
if (value instanceof Error) return value.message;
|
|
7374
|
-
const status = statusFromError(value);
|
|
7375
|
-
if (status) return `HTTP ${status}`;
|
|
7376
|
-
return String(value);
|
|
7377
|
-
}
|
|
7378
|
-
|
|
7379
6895
|
// src/shared/subscription.ts
|
|
7380
6896
|
var ENTITLED_STATUSES = /* @__PURE__ */ new Set([
|
|
7381
6897
|
"active",
|
|
@@ -7557,7 +7073,6 @@ export {
|
|
|
7557
7073
|
SYSTEM_COLLECTION_SCHEMAS,
|
|
7558
7074
|
SYSTEM_MANAGED_COLUMNS,
|
|
7559
7075
|
SchemaRegistry,
|
|
7560
|
-
SecretsRoom,
|
|
7561
7076
|
SubscriptionAuthError,
|
|
7562
7077
|
SubscriptionRequiredError,
|
|
7563
7078
|
USERS_COLUMNS,
|
|
@@ -7594,7 +7109,6 @@ export {
|
|
|
7594
7109
|
createDeepSpaceAI,
|
|
7595
7110
|
createDeepSpaceAuth,
|
|
7596
7111
|
createScopedR2Handler,
|
|
7597
|
-
createSecrets,
|
|
7598
7112
|
dataToColumnValues,
|
|
7599
7113
|
decodeJwtPayload,
|
|
7600
7114
|
deleteChatCascade,
|