@hasna/todos 0.15.32 → 0.15.34
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/cloud-router.d.ts +32 -46
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/index.js +124 -101
- package/dist/cli/stage-a.d.ts +3 -1
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +32 -26
- package/dist/index.js +92 -87
- package/dist/lib/assignee-validation.d.ts.map +1 -1
- package/dist/mcp/index.js +93 -87
- package/dist/mcp.js +2 -4
- package/dist/project-registration/authority.d.ts.map +1 -1
- package/dist/project-registration.js +52 -30
- package/dist/registry.js +32 -26
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +1311 -7260
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/config.d.ts +24 -4
- package/dist/storage/config.d.ts.map +1 -1
- package/dist/storage/hybrid.d.ts +5 -3
- package/dist/storage/hybrid.d.ts.map +1 -1
- package/dist/storage.js +31 -23
- package/dist/task-manifest.js +4 -4
- package/dist/testing.d.ts +16 -7
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +10 -6
- package/package.json +2 -4
package/dist/mcp/index.js
CHANGED
|
@@ -4129,6 +4129,7 @@ __export(exports_config, {
|
|
|
4129
4129
|
TODOS_STORAGE_FALLBACK_ENV: () => TODOS_STORAGE_FALLBACK_ENV,
|
|
4130
4130
|
TODOS_STORAGE_ENV: () => TODOS_STORAGE_ENV,
|
|
4131
4131
|
STORAGE_TABLES: () => STORAGE_TABLES,
|
|
4132
|
+
REMOVED_STORAGE_MODE_ENV_KEYS: () => REMOVED_STORAGE_MODE_ENV_KEYS,
|
|
4132
4133
|
CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV: () => CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV,
|
|
4133
4134
|
CANONICAL_TODOS_RDS_DATABASE: () => CANONICAL_TODOS_RDS_DATABASE,
|
|
4134
4135
|
CANONICAL_TODOS_RDS_CLUSTER_ENV: () => CANONICAL_TODOS_RDS_CLUSTER_ENV
|
|
@@ -4190,25 +4191,36 @@ function assertTodosRemoteStorageConfig(config) {
|
|
|
4190
4191
|
if (!isTodosPostgresBackend(config))
|
|
4191
4192
|
return;
|
|
4192
4193
|
if (!config.database?.url) {
|
|
4193
|
-
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when
|
|
4194
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when the postgresql backend is selected`);
|
|
4194
4195
|
}
|
|
4195
4196
|
}
|
|
4196
4197
|
function parseStorageBackend(value) {
|
|
4197
4198
|
const normalized = clean(value)?.toLowerCase();
|
|
4198
4199
|
if (!normalized)
|
|
4199
4200
|
return "sqlite";
|
|
4200
|
-
if (normalized === "sqlite"
|
|
4201
|
-
return
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4201
|
+
if (normalized === "sqlite")
|
|
4202
|
+
return "sqlite";
|
|
4203
|
+
if (normalized === "postgres" || normalized === "postgresql")
|
|
4204
|
+
return "postgres";
|
|
4205
|
+
if (["local", "remote", "cloud", "hybrid", "self_hosted"].includes(normalized)) {
|
|
4206
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} selects the backend. Deployment modes no longer exist: ` + `delete the storage-mode variable and set ${TODOS_STORAGE_ENV.databaseUrl} to select the ` + `postgresql backend, or leave it unset for sqlite.`);
|
|
4207
|
+
}
|
|
4208
|
+
throw new Error(`Storage backend must be sqlite or postgres`);
|
|
4206
4209
|
}
|
|
4207
4210
|
function parseStorageMode(value) {
|
|
4208
4211
|
return parseStorageBackend(value);
|
|
4209
4212
|
}
|
|
4210
4213
|
function getTodosStorageBackend(env = process.env) {
|
|
4211
|
-
|
|
4214
|
+
for (const key of REMOVED_STORAGE_MODE_ENV_KEYS) {
|
|
4215
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
4216
|
+
throw new Error(`${key} was removed. Deployment modes no longer exist: delete the storage-mode variable. ` + `Set ${TODOS_STORAGE_ENV.databaseUrl} to select the postgresql backend, ` + `or leave it unset for sqlite.`);
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
if (!getTodosStorageDatabaseUrl(env))
|
|
4220
|
+
return "sqlite";
|
|
4221
|
+
if (isTodosShadowEnabled(env))
|
|
4222
|
+
return "sqlite";
|
|
4223
|
+
return "postgres";
|
|
4212
4224
|
}
|
|
4213
4225
|
function getTodosStorageMode(env = process.env) {
|
|
4214
4226
|
return getTodosStorageBackend(env);
|
|
@@ -4282,7 +4294,7 @@ function parsePositiveInteger(value, fallback) {
|
|
|
4282
4294
|
}
|
|
4283
4295
|
return parsed;
|
|
4284
4296
|
}
|
|
4285
|
-
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos"
|
|
4297
|
+
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, REMOVED_STORAGE_MODE_ENV_KEYS, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos";
|
|
4286
4298
|
var init_config = __esm(() => {
|
|
4287
4299
|
TODOS_STORAGE_TABLES = [
|
|
4288
4300
|
"todos_sync_records",
|
|
@@ -4290,7 +4302,6 @@ var init_config = __esm(() => {
|
|
|
4290
4302
|
];
|
|
4291
4303
|
STORAGE_TABLES = TODOS_STORAGE_TABLES;
|
|
4292
4304
|
TODOS_STORAGE_ENV = {
|
|
4293
|
-
mode: "HASNA_TODOS_STORAGE_MODE",
|
|
4294
4305
|
shadow: "HASNA_TODOS_SHADOW",
|
|
4295
4306
|
databaseUrl: "HASNA_TODOS_DATABASE_URL",
|
|
4296
4307
|
databaseSsl: "HASNA_TODOS_DATABASE_SSL",
|
|
@@ -4307,7 +4318,6 @@ var init_config = __esm(() => {
|
|
|
4307
4318
|
syncDryRun: "HASNA_TODOS_SYNC_DRY_RUN"
|
|
4308
4319
|
};
|
|
4309
4320
|
TODOS_STORAGE_FALLBACK_ENV = {
|
|
4310
|
-
mode: "TODOS_STORAGE_MODE",
|
|
4311
4321
|
shadow: "TODOS_SHADOW",
|
|
4312
4322
|
databaseUrl: "TODOS_DATABASE_URL",
|
|
4313
4323
|
databaseSsl: "TODOS_DATABASE_SSL",
|
|
@@ -4323,14 +4333,12 @@ var init_config = __esm(() => {
|
|
|
4323
4333
|
syncBatchSize: "TODOS_SYNC_BATCH_SIZE",
|
|
4324
4334
|
syncDryRun: "TODOS_SYNC_DRY_RUN"
|
|
4325
4335
|
};
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
cloud: "postgres"
|
|
4333
|
-
};
|
|
4336
|
+
REMOVED_STORAGE_MODE_ENV_KEYS = [
|
|
4337
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
4338
|
+
"HASNA_TODOS_MODE",
|
|
4339
|
+
"TODOS_STORAGE_MODE",
|
|
4340
|
+
"TODOS_MODE"
|
|
4341
|
+
];
|
|
4334
4342
|
});
|
|
4335
4343
|
|
|
4336
4344
|
// src/storage/shadow-outbox-schema.ts
|
|
@@ -9677,8 +9685,8 @@ var init_secret_redaction = __esm(() => {
|
|
|
9677
9685
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
9678
9686
|
DEFAULT_PATTERNS = [
|
|
9679
9687
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
9680
|
-
{ name: "github_pat", pattern: /\
|
|
9681
|
-
{ name: "github_oauth", pattern: /\
|
|
9688
|
+
{ name: "github_pat", pattern: /\bgh[p]_[a-zA-Z0-9]{20,}\b/g },
|
|
9689
|
+
{ name: "github_oauth", pattern: /\bgh[o]_[a-zA-Z0-9]{20,}\b/g },
|
|
9682
9690
|
{ name: "aws_access_key", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
9683
9691
|
{ name: "bearer_token", pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+=*\b/gi },
|
|
9684
9692
|
{ name: "jwt", pattern: /\beyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g },
|
|
@@ -9690,7 +9698,7 @@ var init_secret_redaction = __esm(() => {
|
|
|
9690
9698
|
/example\.com/i,
|
|
9691
9699
|
/your-api-key-here/i,
|
|
9692
9700
|
/sk-test/i,
|
|
9693
|
-
/
|
|
9701
|
+
/gh[p]_xxx/i
|
|
9694
9702
|
];
|
|
9695
9703
|
customRedactors = [];
|
|
9696
9704
|
});
|
|
@@ -21093,40 +21101,38 @@ var init_page_validation = __esm(() => {
|
|
|
21093
21101
|
|
|
21094
21102
|
// src/cli/cloud-router.ts
|
|
21095
21103
|
import { resolveStorageClient } from "@hasna/contracts/client/storage";
|
|
21096
|
-
import { normalizeStorageMode } from "@hasna/contracts/mode";
|
|
21097
21104
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
21098
21105
|
import { resolve as resolvePath } from "path";
|
|
21099
|
-
function
|
|
21100
|
-
const
|
|
21101
|
-
|
|
21106
|
+
function assertNoLegacyStorageMode(env = process.env) {
|
|
21107
|
+
for (const key of LEGACY_STORAGE_MODE_KEYS) {
|
|
21108
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
21109
|
+
throw new Error(`REMOTE_STORAGE_MODE_REMOVED: ${key} was removed. Deployment modes no longer exist: delete the storage-mode variable. ` + `The client uses the on-box SQLite store, or the HTTP API selected by ` + `HASNA_TODOS_API_URL + HASNA_TODOS_API_KEY. ` + `On the server, set HASNA_TODOS_DATABASE_URL to select the postgresql backend, ` + `or leave it unset for sqlite.`);
|
|
21110
|
+
}
|
|
21111
|
+
}
|
|
21102
21112
|
}
|
|
21103
21113
|
function resolveTodosCliStorageMode(env = process.env) {
|
|
21104
|
-
|
|
21105
|
-
|
|
21106
|
-
|
|
21107
|
-
|
|
21114
|
+
assertNoLegacyStorageMode(env);
|
|
21115
|
+
const urlValue = env.HASNA_TODOS_API_URL?.trim();
|
|
21116
|
+
const keyValue = env.HASNA_TODOS_API_KEY?.trim();
|
|
21117
|
+
if (urlValue && keyValue) {
|
|
21118
|
+
return {
|
|
21119
|
+
mode: "http",
|
|
21120
|
+
transport: "http",
|
|
21121
|
+
selected: true,
|
|
21122
|
+
source: "HASNA_TODOS_API_URL+HASNA_TODOS_API_KEY"
|
|
21123
|
+
};
|
|
21108
21124
|
}
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
for (const [source, value] of [
|
|
21112
|
-
["HASNA_TODOS_STORAGE_MODE", canonical],
|
|
21113
|
-
["TODOS_STORAGE_MODE", fallback]
|
|
21114
|
-
]) {
|
|
21115
|
-
if (value && !(value in TRANSPORT_TOKENS)) {
|
|
21116
|
-
throw new Error(`REMOTE_STORAGE_MODE_INVALID: ${source}=${value} must be sqlite (local file) or http (hosted /v1 authority); ` + "legacy values local and remote are accepted; " + "local SQLite fallback is disabled for invalid routing state");
|
|
21117
|
-
}
|
|
21125
|
+
if (urlValue) {
|
|
21126
|
+
throw new Error("REMOTE_API_KEY_MISSING: remote Todos storage requires HASNA_TODOS_API_KEY; local SQLite fallback is disabled");
|
|
21118
21127
|
}
|
|
21119
|
-
|
|
21120
|
-
|
|
21121
|
-
if (canonicalTransport && fallbackTransport && canonicalTransport !== fallbackTransport) {
|
|
21122
|
-
throw new Error(`REMOTE_STORAGE_MODE_CONFLICT: HASNA_TODOS_STORAGE_MODE=${canonical} conflicts with ` + `TODOS_STORAGE_MODE=${fallback}; local SQLite fallback is disabled`);
|
|
21128
|
+
if (keyValue) {
|
|
21129
|
+
throw new Error("REMOTE_API_URL_MISSING: remote Todos storage requires HASNA_TODOS_API_URL; local SQLite fallback is disabled");
|
|
21123
21130
|
}
|
|
21124
|
-
const transport = canonicalTransport ?? fallbackTransport ?? "sqlite";
|
|
21125
21131
|
return {
|
|
21126
|
-
mode:
|
|
21127
|
-
transport,
|
|
21128
|
-
selected:
|
|
21129
|
-
source:
|
|
21132
|
+
mode: "sqlite",
|
|
21133
|
+
transport: "sqlite",
|
|
21134
|
+
selected: false,
|
|
21135
|
+
source: "default"
|
|
21130
21136
|
};
|
|
21131
21137
|
}
|
|
21132
21138
|
function requestedTransport(env) {
|
|
@@ -21170,7 +21176,7 @@ function getTodosRemoteAuthorityConfigStatus(env = process.env) {
|
|
|
21170
21176
|
return {
|
|
21171
21177
|
selected: true,
|
|
21172
21178
|
ok: false,
|
|
21173
|
-
mode:
|
|
21179
|
+
mode: "invalid",
|
|
21174
21180
|
api_url_configured: Boolean(env.HASNA_TODOS_API_URL?.trim()),
|
|
21175
21181
|
api_key_configured: Boolean(env.HASNA_TODOS_API_KEY?.trim()),
|
|
21176
21182
|
v1_base_url: null,
|
|
@@ -21216,27 +21222,12 @@ function getTodosRemoteAuthorityConfigStatus(env = process.env) {
|
|
|
21216
21222
|
local_fallback: false
|
|
21217
21223
|
};
|
|
21218
21224
|
}
|
|
21219
|
-
function serverStorageMode(normalize = normalizeStorageMode) {
|
|
21220
|
-
const useCache = normalize === normalizeStorageMode;
|
|
21221
|
-
if (useCache && cachedServerMode !== null)
|
|
21222
|
-
return cachedServerMode;
|
|
21223
|
-
for (const candidate of SERVER_MODE_CANDIDATES) {
|
|
21224
|
-
try {
|
|
21225
|
-
normalize(candidate);
|
|
21226
|
-
if (useCache)
|
|
21227
|
-
cachedServerMode = candidate;
|
|
21228
|
-
return candidate;
|
|
21229
|
-
} catch {}
|
|
21230
|
-
}
|
|
21231
|
-
throw new Error(`REMOTE_STORAGE_MODE_UNSUPPORTED: no known server storage mode is accepted by the installed ` + `@hasna/contracts (tried ${SERVER_MODE_CANDIDATES.join(", ")}); the storage-mode enum has changed. ` + `Add the new server token to SERVER_MODE_CANDIDATES in src/cli/cloud-router.ts; ` + `local SQLite fallback is disabled.`);
|
|
21232
|
-
}
|
|
21233
21225
|
function requireTodosRemoteAuthorityEnv(env) {
|
|
21234
21226
|
const status = getTodosRemoteAuthorityConfigStatus(env);
|
|
21235
21227
|
if (!status.ok)
|
|
21236
21228
|
throw new Error(status.issues[0]);
|
|
21237
21229
|
return {
|
|
21238
21230
|
...env,
|
|
21239
|
-
HASNA_TODOS_STORAGE_MODE: serverStorageMode(),
|
|
21240
21231
|
HASNA_TODOS_API_URL: status.v1_base_url.replace(/\/v1$/, ""),
|
|
21241
21232
|
HASNA_TODOS_API_KEY: env.HASNA_TODOS_API_KEY.trim()
|
|
21242
21233
|
};
|
|
@@ -21312,7 +21303,7 @@ async function requiredRemoteRoute(client, route, request, recognized404Codes =
|
|
|
21312
21303
|
return await request();
|
|
21313
21304
|
} catch (error) {
|
|
21314
21305
|
const status = error && typeof error === "object" ? error.status : undefined;
|
|
21315
|
-
if (status === 404) {
|
|
21306
|
+
if (status === 404 || status === 405) {
|
|
21316
21307
|
const body = error && typeof error === "object" ? error.body : undefined;
|
|
21317
21308
|
const code = body && typeof body === "object" && !Array.isArray(body) ? body.code : undefined;
|
|
21318
21309
|
if (typeof code === "string" && recognized404Codes.includes(code))
|
|
@@ -21328,7 +21319,12 @@ function getTodosCloudClient(env = process.env) {
|
|
|
21328
21319
|
const resolved = resolveStorageClient("todos", requireTodosRemoteAuthorityEnv(env), {
|
|
21329
21320
|
fetchImpl: (input, init) => globalThis.fetch(input, { ...init, redirect: "manual" })
|
|
21330
21321
|
});
|
|
21331
|
-
|
|
21322
|
+
if (resolved.transport === "cloud-http")
|
|
21323
|
+
return protectRemoteClient(resolved.client);
|
|
21324
|
+
const transportName = resolved.transport;
|
|
21325
|
+
if (transportName === "http")
|
|
21326
|
+
return protectRemoteClient(resolved.client);
|
|
21327
|
+
return null;
|
|
21332
21328
|
}
|
|
21333
21329
|
function unwrapTask(raw) {
|
|
21334
21330
|
if (raw && typeof raw === "object" && "task" in raw) {
|
|
@@ -21799,7 +21795,7 @@ async function cloudResolveTaskListRef(client, ref, projectId) {
|
|
|
21799
21795
|
return input.toLowerCase();
|
|
21800
21796
|
return (await cloudResolveTaskList(client, ref, projectId)).id;
|
|
21801
21797
|
}
|
|
21802
|
-
var UUID_RE,
|
|
21798
|
+
var UUID_RE, completionCapabilityCache, retryCapabilityCache, taskCreatorCapabilityCache, gitRefCapabilityCache, remoteCommandCapabilityCache, LEGACY_STORAGE_MODE_KEYS, PRIORITY_RANK, listTagsCapabilityCache;
|
|
21803
21799
|
var init_cloud_router = __esm(() => {
|
|
21804
21800
|
init_types();
|
|
21805
21801
|
init_redaction();
|
|
@@ -21808,21 +21804,17 @@ var init_cloud_router = __esm(() => {
|
|
|
21808
21804
|
init_adoption_validation();
|
|
21809
21805
|
init_page_validation();
|
|
21810
21806
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21811
|
-
TRANSPORT_TOKENS = {
|
|
21812
|
-
sqlite: "sqlite",
|
|
21813
|
-
http: "http",
|
|
21814
|
-
local: "sqlite",
|
|
21815
|
-
remote: "http",
|
|
21816
|
-
self_hosted: "http",
|
|
21817
|
-
cloud: "http",
|
|
21818
|
-
hybrid: "http"
|
|
21819
|
-
};
|
|
21820
21807
|
completionCapabilityCache = new Map;
|
|
21821
21808
|
retryCapabilityCache = new Map;
|
|
21822
21809
|
taskCreatorCapabilityCache = new Map;
|
|
21823
21810
|
gitRefCapabilityCache = new Map;
|
|
21824
21811
|
remoteCommandCapabilityCache = new Map;
|
|
21825
|
-
|
|
21812
|
+
LEGACY_STORAGE_MODE_KEYS = [
|
|
21813
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
21814
|
+
"HASNA_TODOS_MODE",
|
|
21815
|
+
"TODOS_STORAGE_MODE",
|
|
21816
|
+
"TODOS_MODE"
|
|
21817
|
+
];
|
|
21826
21818
|
PRIORITY_RANK = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
21827
21819
|
listTagsCapabilityCache = new Map;
|
|
21828
21820
|
});
|
|
@@ -35939,7 +35931,7 @@ var package_default;
|
|
|
35939
35931
|
var init_package = __esm(() => {
|
|
35940
35932
|
package_default = {
|
|
35941
35933
|
name: "@hasna/todos",
|
|
35942
|
-
version: "0.15.
|
|
35934
|
+
version: "0.15.34",
|
|
35943
35935
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
35944
35936
|
type: "module",
|
|
35945
35937
|
main: "dist/index.js",
|
|
@@ -36013,9 +36005,7 @@ var init_package = __esm(() => {
|
|
|
36013
36005
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
36014
36006
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
36015
36007
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
36016
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
36017
|
-
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
36018
|
-
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
36008
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
36019
36009
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
36020
36010
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
36021
36011
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
@@ -46248,7 +46238,7 @@ function postgresTodosSyncSchemaSql(tableName = DEFAULT_TODOS_POSTGRES_SYNC_TABL
|
|
|
46248
46238
|
AS $$ SELECT unaccent('unaccent', $1) $$`,
|
|
46249
46239
|
`CREATE OR REPLACE FUNCTION todos_try_timestamptz(text)
|
|
46250
46240
|
RETURNS timestamptz
|
|
46251
|
-
LANGUAGE plpgsql IMMUTABLE PARALLEL
|
|
46241
|
+
LANGUAGE plpgsql IMMUTABLE PARALLEL UNSAFE
|
|
46252
46242
|
SET DateStyle TO 'ISO, YMD'
|
|
46253
46243
|
AS $$
|
|
46254
46244
|
BEGIN
|
|
@@ -51853,9 +51843,14 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
51853
51843
|
if (request.max_items !== 1) {
|
|
51854
51844
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_INVALID_BOUNDS", "max_items must be exactly 1 for terminal receipt lookup");
|
|
51855
51845
|
}
|
|
51856
|
-
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id
|
|
51846
|
+
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id) {
|
|
51857
51847
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_CAPABILITY_MISMATCH", "receipt lookup does not match this authority capability identity");
|
|
51858
51848
|
}
|
|
51849
|
+
requireString(request.corpus_id, "corpus_id", {
|
|
51850
|
+
min: 3,
|
|
51851
|
+
max: 128,
|
|
51852
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
51853
|
+
});
|
|
51859
51854
|
requireString(request.authority_route, "authority_route", {
|
|
51860
51855
|
min: 3,
|
|
51861
51856
|
max: 128,
|
|
@@ -51886,6 +51881,7 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
51886
51881
|
}
|
|
51887
51882
|
const receipt = await this.backend.getReceiptForLookup({
|
|
51888
51883
|
...authorityScope(this.capabilityValue),
|
|
51884
|
+
corpus_id: request.corpus_id,
|
|
51889
51885
|
route: request.authority_route,
|
|
51890
51886
|
package_version: request.package_version,
|
|
51891
51887
|
operation_id: request.operation_id,
|
|
@@ -51990,9 +51986,15 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
51990
51986
|
max: 128,
|
|
51991
51987
|
pattern: PACKAGE_VERSION_PATTERN
|
|
51992
51988
|
});
|
|
51989
|
+
requireString(sourceRequest.corpus_id, "corpus_id", {
|
|
51990
|
+
min: 3,
|
|
51991
|
+
max: 128,
|
|
51992
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
51993
|
+
});
|
|
51993
51994
|
assertForwardRequest(sourceRequest, {
|
|
51994
51995
|
...this.capabilityValue,
|
|
51995
|
-
package_version: sourceRequest.package_version
|
|
51996
|
+
package_version: sourceRequest.package_version,
|
|
51997
|
+
corpus_id: sourceRequest.corpus_id
|
|
51996
51998
|
});
|
|
51997
51999
|
const validation = await this.backend.transaction(async (transaction) => {
|
|
51998
52000
|
const storedSource = await transaction.getReceiptById(sourceReceipt.receipt_id);
|
|
@@ -52007,7 +52009,11 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
52007
52009
|
if (!receiptLineageMatches(storedSource) || !receiptLineageMatches(accepted) || storedSource.outcome === "duplicate_of_accepted" && (storedSource.duplicate_of_receipt_id !== accepted.receipt_id || storedSource.target_id !== accepted.target_id || storedSource.result_revision !== accepted.result_revision || storedSource.result_digest !== accepted.result_digest)) {
|
|
52008
52010
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "receipt authority, operation, request, precondition, or normalized-call lineage changed");
|
|
52009
52011
|
}
|
|
52010
|
-
const binding = await transaction.getBinding(
|
|
52012
|
+
const binding = await transaction.getBinding({
|
|
52013
|
+
authority_id: sourceRequest.authority_id,
|
|
52014
|
+
tenant_id: sourceRequest.tenant_id,
|
|
52015
|
+
corpus_id: sourceRequest.corpus_id
|
|
52016
|
+
}, sourceRequest.resource_kind, sourceRequest.target_selector);
|
|
52011
52017
|
if (!binding || binding.state !== "accepted" || binding.operation_id !== sourceRequest.operation_id || binding.step_id !== sourceRequest.step_id || binding.direction !== "forward" || binding.idempotency_key !== sourceRequest.idempotency_key || binding.request_digest !== sourceRequest.request_digest || binding.precondition_digest !== sourceRequest.precondition_digest || binding.normalized_call_digest !== accepted.normalized_call_digest || binding.target_id !== accepted.target_id || binding.accepted_receipt_id !== accepted.receipt_id || binding.result_revision !== accepted.result_revision || binding.result_digest !== accepted.result_digest) {
|
|
52012
52018
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "accepted binding does not match the exact accepted receipt and source lineage");
|
|
52013
52019
|
}
|
|
@@ -59829,8 +59835,8 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
59829
59835
|
}
|
|
59830
59836
|
const created = await store.tasks.create(body2, storageContext);
|
|
59831
59837
|
const persisted = created?.id ? await store.tasks.get(created.id, storageContext) : null;
|
|
59832
|
-
if (!persisted || persisted.id !== created.id || (persisted.parent_id ?? null) !== (body2.parent_id ?? null) || (persisted.plan_id ?? null) !== (body2.plan_id ?? null)) {
|
|
59833
|
-
return error(500, "TASK_CREATE_PERSISTENCE_UNVERIFIED: task create was acknowledged but authoritative readback did not return the same stored task id, parent_id, and
|
|
59838
|
+
if (!persisted || persisted.id !== created.id || (persisted.parent_id ?? null) !== (body2.parent_id ?? null) || (persisted.plan_id ?? null) !== (body2.plan_id ?? null) || body2.created_by !== undefined && persisted.created_by !== body2.created_by) {
|
|
59839
|
+
return error(500, "TASK_CREATE_PERSISTENCE_UNVERIFIED: task create was acknowledged but authoritative readback did not return the same stored task id, parent_id, plan_id, and explicit created_by", { code: "TASK_CREATE_PERSISTENCE_UNVERIFIED" });
|
|
59834
59840
|
}
|
|
59835
59841
|
return json5({ task: persisted }, 201);
|
|
59836
59842
|
}
|
package/dist/mcp.js
CHANGED
|
@@ -41,7 +41,7 @@ var __require = import.meta.require;
|
|
|
41
41
|
// package.json
|
|
42
42
|
var package_default = {
|
|
43
43
|
name: "@hasna/todos",
|
|
44
|
-
version: "0.15.
|
|
44
|
+
version: "0.15.34",
|
|
45
45
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
46
46
|
type: "module",
|
|
47
47
|
main: "dist/index.js",
|
|
@@ -115,9 +115,7 @@ var package_default = {
|
|
|
115
115
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
116
116
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
117
117
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
118
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
119
|
-
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
120
|
-
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
118
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
121
119
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
122
120
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
123
121
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/project-registration/authority.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAEV,+BAA+B,EAMhC,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,8CAA8C,EACnD,KAAK,sCAAsC,EAC5C,MAAM,eAAe,CAAC;AAEvB,OAAO,EAIL,KAAK,iCAAiC,EACtC,KAAK,wCAAwC,EAE7C,KAAK,kCAAkC,EACvC,KAAK,iCAAiC,EAEtC,KAAK,2CAA2C,EAChD,KAAK,qCAAqC,EAC1C,KAAK,oCAAoC,EACzC,KAAK,+BAA+B,EACpC,KAAK,8BAA8B,EACnC,KAAK,+BAA+B,EACpC,KAAK,oCAAoC,EACzC,KAAK,2CAA2C,EAChD,KAAK,wCAAwC,EAE7C,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,EACrC,MAAM,YAAY,CAAC;AAuBpB,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEvE;AAaD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIrE;AAED,wBAAgB,4CAA4C,CAAC,KAAK,EAAE;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,MAAM,CAKT;AA0zBD,qBAAa,6CACb,YAAW,iCAAiC;IAOxC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,QAAQ,CAAC,SAAS,EAAG,OAAO,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA4D;gBAGxE,OAAO,EAAE,+BAA+B,EACzD,OAAO,GAAE,wCAA6C;IAyBlD,UAAU,IAAI,OAAO,CAAC,kCAAkC,CAAC;YAOjD,KAAK;YAiBL,WAAW;YASX,YAAY;YAgBZ,WAAW;YAuBX,yBAAyB;YA2DzB,YAAY;IAsHpB,MAAM,CACV,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,+BAA+B,CAAC;YAsG7B,kBAAkB;IAiE1B,SAAS,CAAC,OAAO,EAAE;QACvB,aAAa,EAAE,oCAAoC,CAAC;QACpD,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;QAChB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,8BAA8B,CAAC;IA0BrC,aAAa,CACjB,OAAO,EAAE,qCAAqC,GAC7C,OAAO,CAAC,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/project-registration/authority.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,OAAO,KAAK,EAEV,+BAA+B,EAMhC,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,8CAA8C,EACnD,KAAK,sCAAsC,EAC5C,MAAM,eAAe,CAAC;AAEvB,OAAO,EAIL,KAAK,iCAAiC,EACtC,KAAK,wCAAwC,EAE7C,KAAK,kCAAkC,EACvC,KAAK,iCAAiC,EAEtC,KAAK,2CAA2C,EAChD,KAAK,qCAAqC,EAC1C,KAAK,oCAAoC,EACzC,KAAK,+BAA+B,EACpC,KAAK,8BAA8B,EACnC,KAAK,+BAA+B,EACpC,KAAK,oCAAoC,EACzC,KAAK,2CAA2C,EAChD,KAAK,wCAAwC,EAE7C,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,EACrC,MAAM,YAAY,CAAC;AAuBpB,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEvE;AAaD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIrE;AAED,wBAAgB,4CAA4C,CAAC,KAAK,EAAE;IAClE,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,iCAAiC,CAAC;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,MAAM,CAKT;AA0zBD,qBAAa,6CACb,YAAW,iCAAiC;IAOxC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,QAAQ,CAAC,SAAS,EAAG,OAAO,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IACrE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAA4D;gBAGxE,OAAO,EAAE,+BAA+B,EACzD,OAAO,GAAE,wCAA6C;IAyBlD,UAAU,IAAI,OAAO,CAAC,kCAAkC,CAAC;YAOjD,KAAK;YAiBL,WAAW;YASX,YAAY;YAgBZ,WAAW;YAuBX,yBAAyB;YA2DzB,YAAY;IAsHpB,MAAM,CACV,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,+BAA+B,CAAC;YAsG7B,kBAAkB;IAiE1B,SAAS,CAAC,OAAO,EAAE;QACvB,aAAa,EAAE,oCAAoC,CAAC;QACpD,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;QAChB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,cAAc,EAAE,MAAM,CAAC;KACxB,GAAG,OAAO,CAAC,8BAA8B,CAAC;IA0BrC,aAAa,CACjB,OAAO,EAAE,qCAAqC,GAC7C,OAAO,CAAC,oCAAoC,CAAC;IAkF1C,oBAAoB,CACxB,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,wBAAwB,CAAC;IA2I9B,iCAAiC,CACrC,aAAa,EAAE,+BAA+B,EAC9C,aAAa,EAAE,+BAA+B,EAC9C,aAAa,EAAE,2CAA2C,GACzD,OAAO,CAAC,wCAAwC,CAAC;YAwMtC,qBAAqB;IAgC7B,UAAU,CACd,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,+BAA+B,CAAC;IAqLrC,aAAa,CACjB,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,2CAA2C,CAAC;CAuDxD;AAED,wBAAgB,4CAA4C,CAC1D,EAAE,EAAE,QAAQ,EACZ,OAAO,GAAE,wCAA6C,GACrD,iCAAiC,CAKnC;AAED,wBAAgB,+CAA+C,CAC7D,MAAM,EAAE,sCAAsC,EAC9C,OAAO,GAAE,wCAAwC,GAC7C,8CAAmD,GACtD,iCAAiC,CAenC"}
|
|
@@ -757,8 +757,8 @@ var init_secret_redaction = __esm(() => {
|
|
|
757
757
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
758
758
|
DEFAULT_PATTERNS = [
|
|
759
759
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
760
|
-
{ name: "github_pat", pattern: /\
|
|
761
|
-
{ name: "github_oauth", pattern: /\
|
|
760
|
+
{ name: "github_pat", pattern: /\bgh[p]_[a-zA-Z0-9]{20,}\b/g },
|
|
761
|
+
{ name: "github_oauth", pattern: /\bgh[o]_[a-zA-Z0-9]{20,}\b/g },
|
|
762
762
|
{ name: "aws_access_key", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
763
763
|
{ name: "bearer_token", pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+=*\b/gi },
|
|
764
764
|
{ name: "jwt", pattern: /\beyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g },
|
|
@@ -770,7 +770,7 @@ var init_secret_redaction = __esm(() => {
|
|
|
770
770
|
/example\.com/i,
|
|
771
771
|
/your-api-key-here/i,
|
|
772
772
|
/sk-test/i,
|
|
773
|
-
/
|
|
773
|
+
/gh[p]_xxx/i
|
|
774
774
|
];
|
|
775
775
|
customRedactors = [];
|
|
776
776
|
});
|
|
@@ -4883,6 +4883,7 @@ __export(exports_config, {
|
|
|
4883
4883
|
TODOS_STORAGE_FALLBACK_ENV: () => TODOS_STORAGE_FALLBACK_ENV,
|
|
4884
4884
|
TODOS_STORAGE_ENV: () => TODOS_STORAGE_ENV,
|
|
4885
4885
|
STORAGE_TABLES: () => STORAGE_TABLES,
|
|
4886
|
+
REMOVED_STORAGE_MODE_ENV_KEYS: () => REMOVED_STORAGE_MODE_ENV_KEYS,
|
|
4886
4887
|
CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV: () => CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV,
|
|
4887
4888
|
CANONICAL_TODOS_RDS_DATABASE: () => CANONICAL_TODOS_RDS_DATABASE,
|
|
4888
4889
|
CANONICAL_TODOS_RDS_CLUSTER_ENV: () => CANONICAL_TODOS_RDS_CLUSTER_ENV
|
|
@@ -4944,25 +4945,36 @@ function assertTodosRemoteStorageConfig(config) {
|
|
|
4944
4945
|
if (!isTodosPostgresBackend(config))
|
|
4945
4946
|
return;
|
|
4946
4947
|
if (!config.database?.url) {
|
|
4947
|
-
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when
|
|
4948
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when the postgresql backend is selected`);
|
|
4948
4949
|
}
|
|
4949
4950
|
}
|
|
4950
4951
|
function parseStorageBackend(value) {
|
|
4951
4952
|
const normalized = clean(value)?.toLowerCase();
|
|
4952
4953
|
if (!normalized)
|
|
4953
4954
|
return "sqlite";
|
|
4954
|
-
if (normalized === "sqlite"
|
|
4955
|
-
return
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4955
|
+
if (normalized === "sqlite")
|
|
4956
|
+
return "sqlite";
|
|
4957
|
+
if (normalized === "postgres" || normalized === "postgresql")
|
|
4958
|
+
return "postgres";
|
|
4959
|
+
if (["local", "remote", "cloud", "hybrid", "self_hosted"].includes(normalized)) {
|
|
4960
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} selects the backend. Deployment modes no longer exist: ` + `delete the storage-mode variable and set ${TODOS_STORAGE_ENV.databaseUrl} to select the ` + `postgresql backend, or leave it unset for sqlite.`);
|
|
4961
|
+
}
|
|
4962
|
+
throw new Error(`Storage backend must be sqlite or postgres`);
|
|
4960
4963
|
}
|
|
4961
4964
|
function parseStorageMode(value) {
|
|
4962
4965
|
return parseStorageBackend(value);
|
|
4963
4966
|
}
|
|
4964
4967
|
function getTodosStorageBackend(env = process.env) {
|
|
4965
|
-
|
|
4968
|
+
for (const key of REMOVED_STORAGE_MODE_ENV_KEYS) {
|
|
4969
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
4970
|
+
throw new Error(`${key} was removed. Deployment modes no longer exist: delete the storage-mode variable. ` + `Set ${TODOS_STORAGE_ENV.databaseUrl} to select the postgresql backend, ` + `or leave it unset for sqlite.`);
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4973
|
+
if (!getTodosStorageDatabaseUrl(env))
|
|
4974
|
+
return "sqlite";
|
|
4975
|
+
if (isTodosShadowEnabled(env))
|
|
4976
|
+
return "sqlite";
|
|
4977
|
+
return "postgres";
|
|
4966
4978
|
}
|
|
4967
4979
|
function getTodosStorageMode(env = process.env) {
|
|
4968
4980
|
return getTodosStorageBackend(env);
|
|
@@ -5036,7 +5048,7 @@ function parsePositiveInteger(value, fallback) {
|
|
|
5036
5048
|
}
|
|
5037
5049
|
return parsed;
|
|
5038
5050
|
}
|
|
5039
|
-
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos"
|
|
5051
|
+
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, REMOVED_STORAGE_MODE_ENV_KEYS, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos";
|
|
5040
5052
|
var init_config2 = __esm(() => {
|
|
5041
5053
|
TODOS_STORAGE_TABLES = [
|
|
5042
5054
|
"todos_sync_records",
|
|
@@ -5044,7 +5056,6 @@ var init_config2 = __esm(() => {
|
|
|
5044
5056
|
];
|
|
5045
5057
|
STORAGE_TABLES = TODOS_STORAGE_TABLES;
|
|
5046
5058
|
TODOS_STORAGE_ENV = {
|
|
5047
|
-
mode: "HASNA_TODOS_STORAGE_MODE",
|
|
5048
5059
|
shadow: "HASNA_TODOS_SHADOW",
|
|
5049
5060
|
databaseUrl: "HASNA_TODOS_DATABASE_URL",
|
|
5050
5061
|
databaseSsl: "HASNA_TODOS_DATABASE_SSL",
|
|
@@ -5061,7 +5072,6 @@ var init_config2 = __esm(() => {
|
|
|
5061
5072
|
syncDryRun: "HASNA_TODOS_SYNC_DRY_RUN"
|
|
5062
5073
|
};
|
|
5063
5074
|
TODOS_STORAGE_FALLBACK_ENV = {
|
|
5064
|
-
mode: "TODOS_STORAGE_MODE",
|
|
5065
5075
|
shadow: "TODOS_SHADOW",
|
|
5066
5076
|
databaseUrl: "TODOS_DATABASE_URL",
|
|
5067
5077
|
databaseSsl: "TODOS_DATABASE_SSL",
|
|
@@ -5077,14 +5087,12 @@ var init_config2 = __esm(() => {
|
|
|
5077
5087
|
syncBatchSize: "TODOS_SYNC_BATCH_SIZE",
|
|
5078
5088
|
syncDryRun: "TODOS_SYNC_DRY_RUN"
|
|
5079
5089
|
};
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
cloud: "postgres"
|
|
5087
|
-
};
|
|
5090
|
+
REMOVED_STORAGE_MODE_ENV_KEYS = [
|
|
5091
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
5092
|
+
"HASNA_TODOS_MODE",
|
|
5093
|
+
"TODOS_STORAGE_MODE",
|
|
5094
|
+
"TODOS_MODE"
|
|
5095
|
+
];
|
|
5088
5096
|
});
|
|
5089
5097
|
|
|
5090
5098
|
// src/storage/shadow-outbox-schema.ts
|
|
@@ -12723,7 +12731,7 @@ import { createHash as createHash7 } from "crypto";
|
|
|
12723
12731
|
// package.json
|
|
12724
12732
|
var package_default = {
|
|
12725
12733
|
name: "@hasna/todos",
|
|
12726
|
-
version: "0.15.
|
|
12734
|
+
version: "0.15.34",
|
|
12727
12735
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12728
12736
|
type: "module",
|
|
12729
12737
|
main: "dist/index.js",
|
|
@@ -12797,9 +12805,7 @@ var package_default = {
|
|
|
12797
12805
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
12798
12806
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
12799
12807
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
12800
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
12801
|
-
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
12802
|
-
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
12808
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
12803
12809
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
12804
12810
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
12805
12811
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
@@ -12963,7 +12969,7 @@ function postgresTodosSyncSchemaSql(tableName = DEFAULT_TODOS_POSTGRES_SYNC_TABL
|
|
|
12963
12969
|
AS $$ SELECT unaccent('unaccent', $1) $$`,
|
|
12964
12970
|
`CREATE OR REPLACE FUNCTION todos_try_timestamptz(text)
|
|
12965
12971
|
RETURNS timestamptz
|
|
12966
|
-
LANGUAGE plpgsql IMMUTABLE PARALLEL
|
|
12972
|
+
LANGUAGE plpgsql IMMUTABLE PARALLEL UNSAFE
|
|
12967
12973
|
SET DateStyle TO 'ISO, YMD'
|
|
12968
12974
|
AS $$
|
|
12969
12975
|
BEGIN
|
|
@@ -19734,9 +19740,14 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
19734
19740
|
if (request.max_items !== 1) {
|
|
19735
19741
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_INVALID_BOUNDS", "max_items must be exactly 1 for terminal receipt lookup");
|
|
19736
19742
|
}
|
|
19737
|
-
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id
|
|
19743
|
+
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id) {
|
|
19738
19744
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_CAPABILITY_MISMATCH", "receipt lookup does not match this authority capability identity");
|
|
19739
19745
|
}
|
|
19746
|
+
requireString(request.corpus_id, "corpus_id", {
|
|
19747
|
+
min: 3,
|
|
19748
|
+
max: 128,
|
|
19749
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
19750
|
+
});
|
|
19740
19751
|
requireString(request.authority_route, "authority_route", {
|
|
19741
19752
|
min: 3,
|
|
19742
19753
|
max: 128,
|
|
@@ -19767,6 +19778,7 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
19767
19778
|
}
|
|
19768
19779
|
const receipt = await this.backend.getReceiptForLookup({
|
|
19769
19780
|
...authorityScope(this.capabilityValue),
|
|
19781
|
+
corpus_id: request.corpus_id,
|
|
19770
19782
|
route: request.authority_route,
|
|
19771
19783
|
package_version: request.package_version,
|
|
19772
19784
|
operation_id: request.operation_id,
|
|
@@ -19871,9 +19883,15 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
19871
19883
|
max: 128,
|
|
19872
19884
|
pattern: PACKAGE_VERSION_PATTERN
|
|
19873
19885
|
});
|
|
19886
|
+
requireString(sourceRequest.corpus_id, "corpus_id", {
|
|
19887
|
+
min: 3,
|
|
19888
|
+
max: 128,
|
|
19889
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
19890
|
+
});
|
|
19874
19891
|
assertForwardRequest(sourceRequest, {
|
|
19875
19892
|
...this.capabilityValue,
|
|
19876
|
-
package_version: sourceRequest.package_version
|
|
19893
|
+
package_version: sourceRequest.package_version,
|
|
19894
|
+
corpus_id: sourceRequest.corpus_id
|
|
19877
19895
|
});
|
|
19878
19896
|
const validation = await this.backend.transaction(async (transaction) => {
|
|
19879
19897
|
const storedSource = await transaction.getReceiptById(sourceReceipt.receipt_id);
|
|
@@ -19888,7 +19906,11 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
19888
19906
|
if (!receiptLineageMatches(storedSource) || !receiptLineageMatches(accepted) || storedSource.outcome === "duplicate_of_accepted" && (storedSource.duplicate_of_receipt_id !== accepted.receipt_id || storedSource.target_id !== accepted.target_id || storedSource.result_revision !== accepted.result_revision || storedSource.result_digest !== accepted.result_digest)) {
|
|
19889
19907
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "receipt authority, operation, request, precondition, or normalized-call lineage changed");
|
|
19890
19908
|
}
|
|
19891
|
-
const binding = await transaction.getBinding(
|
|
19909
|
+
const binding = await transaction.getBinding({
|
|
19910
|
+
authority_id: sourceRequest.authority_id,
|
|
19911
|
+
tenant_id: sourceRequest.tenant_id,
|
|
19912
|
+
corpus_id: sourceRequest.corpus_id
|
|
19913
|
+
}, sourceRequest.resource_kind, sourceRequest.target_selector);
|
|
19892
19914
|
if (!binding || binding.state !== "accepted" || binding.operation_id !== sourceRequest.operation_id || binding.step_id !== sourceRequest.step_id || binding.direction !== "forward" || binding.idempotency_key !== sourceRequest.idempotency_key || binding.request_digest !== sourceRequest.request_digest || binding.precondition_digest !== sourceRequest.precondition_digest || binding.normalized_call_digest !== accepted.normalized_call_digest || binding.target_id !== accepted.target_id || binding.accepted_receipt_id !== accepted.receipt_id || binding.result_revision !== accepted.result_revision || binding.result_digest !== accepted.result_digest) {
|
|
19893
19915
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "accepted binding does not match the exact accepted receipt and source lineage");
|
|
19894
19916
|
}
|