@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/cli/index.js
CHANGED
|
@@ -2123,7 +2123,7 @@ var package_default;
|
|
|
2123
2123
|
var init_package = __esm(() => {
|
|
2124
2124
|
package_default = {
|
|
2125
2125
|
name: "@hasna/todos",
|
|
2126
|
-
version: "0.15.
|
|
2126
|
+
version: "0.15.34",
|
|
2127
2127
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
2128
2128
|
type: "module",
|
|
2129
2129
|
main: "dist/index.js",
|
|
@@ -2197,9 +2197,7 @@ var init_package = __esm(() => {
|
|
|
2197
2197
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
2198
2198
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
2199
2199
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
2200
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
2201
|
-
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
2202
|
-
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
2200
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
2203
2201
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
2204
2202
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
2205
2203
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
@@ -5657,40 +5655,38 @@ var init_page_validation = __esm(() => {
|
|
|
5657
5655
|
|
|
5658
5656
|
// src/cli/cloud-router.ts
|
|
5659
5657
|
import { resolveStorageClient } from "@hasna/contracts/client/storage";
|
|
5660
|
-
import { normalizeStorageMode } from "@hasna/contracts/mode";
|
|
5661
5658
|
import { randomUUID } from "crypto";
|
|
5662
5659
|
import { resolve as resolvePath } from "path";
|
|
5663
|
-
function
|
|
5664
|
-
const
|
|
5665
|
-
|
|
5660
|
+
function assertNoLegacyStorageMode(env = process.env) {
|
|
5661
|
+
for (const key of LEGACY_STORAGE_MODE_KEYS) {
|
|
5662
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
5663
|
+
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.`);
|
|
5664
|
+
}
|
|
5665
|
+
}
|
|
5666
5666
|
}
|
|
5667
5667
|
function resolveTodosCliStorageMode(env = process.env) {
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5668
|
+
assertNoLegacyStorageMode(env);
|
|
5669
|
+
const urlValue = env.HASNA_TODOS_API_URL?.trim();
|
|
5670
|
+
const keyValue = env.HASNA_TODOS_API_KEY?.trim();
|
|
5671
|
+
if (urlValue && keyValue) {
|
|
5672
|
+
return {
|
|
5673
|
+
mode: "http",
|
|
5674
|
+
transport: "http",
|
|
5675
|
+
selected: true,
|
|
5676
|
+
source: "HASNA_TODOS_API_URL+HASNA_TODOS_API_KEY"
|
|
5677
|
+
};
|
|
5672
5678
|
}
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
for (const [source, value] of [
|
|
5676
|
-
["HASNA_TODOS_STORAGE_MODE", canonical],
|
|
5677
|
-
["TODOS_STORAGE_MODE", fallback]
|
|
5678
|
-
]) {
|
|
5679
|
-
if (value && !(value in TRANSPORT_TOKENS)) {
|
|
5680
|
-
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");
|
|
5681
|
-
}
|
|
5679
|
+
if (urlValue) {
|
|
5680
|
+
throw new Error("REMOTE_API_KEY_MISSING: remote Todos storage requires HASNA_TODOS_API_KEY; local SQLite fallback is disabled");
|
|
5682
5681
|
}
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
if (canonicalTransport && fallbackTransport && canonicalTransport !== fallbackTransport) {
|
|
5686
|
-
throw new Error(`REMOTE_STORAGE_MODE_CONFLICT: HASNA_TODOS_STORAGE_MODE=${canonical} conflicts with ` + `TODOS_STORAGE_MODE=${fallback}; local SQLite fallback is disabled`);
|
|
5682
|
+
if (keyValue) {
|
|
5683
|
+
throw new Error("REMOTE_API_URL_MISSING: remote Todos storage requires HASNA_TODOS_API_URL; local SQLite fallback is disabled");
|
|
5687
5684
|
}
|
|
5688
|
-
const transport = canonicalTransport ?? fallbackTransport ?? "sqlite";
|
|
5689
5685
|
return {
|
|
5690
|
-
mode:
|
|
5691
|
-
transport,
|
|
5692
|
-
selected:
|
|
5693
|
-
source:
|
|
5686
|
+
mode: "sqlite",
|
|
5687
|
+
transport: "sqlite",
|
|
5688
|
+
selected: false,
|
|
5689
|
+
source: "default"
|
|
5694
5690
|
};
|
|
5695
5691
|
}
|
|
5696
5692
|
function requestedTransport(env) {
|
|
@@ -5734,7 +5730,7 @@ function getTodosRemoteAuthorityConfigStatus(env = process.env) {
|
|
|
5734
5730
|
return {
|
|
5735
5731
|
selected: true,
|
|
5736
5732
|
ok: false,
|
|
5737
|
-
mode:
|
|
5733
|
+
mode: "invalid",
|
|
5738
5734
|
api_url_configured: Boolean(env.HASNA_TODOS_API_URL?.trim()),
|
|
5739
5735
|
api_key_configured: Boolean(env.HASNA_TODOS_API_KEY?.trim()),
|
|
5740
5736
|
v1_base_url: null,
|
|
@@ -5780,27 +5776,12 @@ function getTodosRemoteAuthorityConfigStatus(env = process.env) {
|
|
|
5780
5776
|
local_fallback: false
|
|
5781
5777
|
};
|
|
5782
5778
|
}
|
|
5783
|
-
function serverStorageMode(normalize = normalizeStorageMode) {
|
|
5784
|
-
const useCache = normalize === normalizeStorageMode;
|
|
5785
|
-
if (useCache && cachedServerMode !== null)
|
|
5786
|
-
return cachedServerMode;
|
|
5787
|
-
for (const candidate of SERVER_MODE_CANDIDATES) {
|
|
5788
|
-
try {
|
|
5789
|
-
normalize(candidate);
|
|
5790
|
-
if (useCache)
|
|
5791
|
-
cachedServerMode = candidate;
|
|
5792
|
-
return candidate;
|
|
5793
|
-
} catch {}
|
|
5794
|
-
}
|
|
5795
|
-
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.`);
|
|
5796
|
-
}
|
|
5797
5779
|
function requireTodosRemoteAuthorityEnv(env) {
|
|
5798
5780
|
const status = getTodosRemoteAuthorityConfigStatus(env);
|
|
5799
5781
|
if (!status.ok)
|
|
5800
5782
|
throw new Error(status.issues[0]);
|
|
5801
5783
|
return {
|
|
5802
5784
|
...env,
|
|
5803
|
-
HASNA_TODOS_STORAGE_MODE: serverStorageMode(),
|
|
5804
5785
|
HASNA_TODOS_API_URL: status.v1_base_url.replace(/\/v1$/, ""),
|
|
5805
5786
|
HASNA_TODOS_API_KEY: env.HASNA_TODOS_API_KEY.trim()
|
|
5806
5787
|
};
|
|
@@ -5876,7 +5857,7 @@ async function requiredRemoteRoute(client, route, request, recognized404Codes =
|
|
|
5876
5857
|
return await request();
|
|
5877
5858
|
} catch (error) {
|
|
5878
5859
|
const status = error && typeof error === "object" ? error.status : undefined;
|
|
5879
|
-
if (status === 404) {
|
|
5860
|
+
if (status === 404 || status === 405) {
|
|
5880
5861
|
const body = error && typeof error === "object" ? error.body : undefined;
|
|
5881
5862
|
const code = body && typeof body === "object" && !Array.isArray(body) ? body.code : undefined;
|
|
5882
5863
|
if (typeof code === "string" && recognized404Codes.includes(code))
|
|
@@ -5892,7 +5873,12 @@ function getTodosCloudClient(env = process.env) {
|
|
|
5892
5873
|
const resolved = resolveStorageClient("todos", requireTodosRemoteAuthorityEnv(env), {
|
|
5893
5874
|
fetchImpl: (input, init) => globalThis.fetch(input, { ...init, redirect: "manual" })
|
|
5894
5875
|
});
|
|
5895
|
-
|
|
5876
|
+
if (resolved.transport === "cloud-http")
|
|
5877
|
+
return protectRemoteClient(resolved.client);
|
|
5878
|
+
const transportName = resolved.transport;
|
|
5879
|
+
if (transportName === "http")
|
|
5880
|
+
return protectRemoteClient(resolved.client);
|
|
5881
|
+
return null;
|
|
5896
5882
|
}
|
|
5897
5883
|
function isCloudRouting(env = process.env) {
|
|
5898
5884
|
return getTodosCloudClient(env) !== null;
|
|
@@ -7397,11 +7383,13 @@ async function cloudUpdateTaskList(client, id, patch) {
|
|
|
7397
7383
|
return unwrapTaskList(await client.update("task-lists", id, patch));
|
|
7398
7384
|
}
|
|
7399
7385
|
async function cloudRenameProject(client, ref, newSlug, name) {
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7386
|
+
return requiredRemoteRoute(client, "/v1/projects/:id/rename", async () => {
|
|
7387
|
+
const id = await cloudResolveProjectRef(client, ref);
|
|
7388
|
+
const normalizedSlug = cloudProjectSlug(newSlug);
|
|
7389
|
+
if (!normalizedSlug)
|
|
7390
|
+
throw new Error("Invalid slug \u2014 must be non-empty kebab-case");
|
|
7391
|
+
return client.transport.post(`/projects/${encodeURIComponent(id)}/rename`, { new_slug: normalizedSlug, ...name !== undefined ? { name } : {} });
|
|
7392
|
+
});
|
|
7405
7393
|
}
|
|
7406
7394
|
async function cloudDeleteTaskList(client, id) {
|
|
7407
7395
|
try {
|
|
@@ -7547,7 +7535,7 @@ async function cloudTimeline(client, options = {}) {
|
|
|
7547
7535
|
const limit = options.limit ?? 50;
|
|
7548
7536
|
return { entries: entries.slice(offset, offset + limit), total, limit, offset };
|
|
7549
7537
|
}
|
|
7550
|
-
var UUID_RE,
|
|
7538
|
+
var UUID_RE, COMPLETION_EVIDENCE_FIELDS, completionCapabilityCache, retryCapabilityCache, taskCreatorCapabilityCache, gitRefCapabilityCache, remoteCommandCapabilityCache, LEGACY_STORAGE_MODE_KEYS, PRIORITY_RANK, listTagsCapabilityCache, PLAN_COMPLETION_PROTECTED_FIELDS, RELATION_HYDRATION_CONCURRENCY = 6;
|
|
7551
7539
|
var init_cloud_router = __esm(() => {
|
|
7552
7540
|
init_types();
|
|
7553
7541
|
init_redaction();
|
|
@@ -7556,15 +7544,6 @@ var init_cloud_router = __esm(() => {
|
|
|
7556
7544
|
init_adoption_validation();
|
|
7557
7545
|
init_page_validation();
|
|
7558
7546
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7559
|
-
TRANSPORT_TOKENS = {
|
|
7560
|
-
sqlite: "sqlite",
|
|
7561
|
-
http: "http",
|
|
7562
|
-
local: "sqlite",
|
|
7563
|
-
remote: "http",
|
|
7564
|
-
self_hosted: "http",
|
|
7565
|
-
cloud: "http",
|
|
7566
|
-
hybrid: "http"
|
|
7567
|
-
};
|
|
7568
7547
|
COMPLETION_EVIDENCE_FIELDS = [
|
|
7569
7548
|
"attachment_ids",
|
|
7570
7549
|
"files_changed",
|
|
@@ -7578,7 +7557,12 @@ var init_cloud_router = __esm(() => {
|
|
|
7578
7557
|
taskCreatorCapabilityCache = new Map;
|
|
7579
7558
|
gitRefCapabilityCache = new Map;
|
|
7580
7559
|
remoteCommandCapabilityCache = new Map;
|
|
7581
|
-
|
|
7560
|
+
LEGACY_STORAGE_MODE_KEYS = [
|
|
7561
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
7562
|
+
"HASNA_TODOS_MODE",
|
|
7563
|
+
"TODOS_STORAGE_MODE",
|
|
7564
|
+
"TODOS_MODE"
|
|
7565
|
+
];
|
|
7582
7566
|
PRIORITY_RANK = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
7583
7567
|
listTagsCapabilityCache = new Map;
|
|
7584
7568
|
PLAN_COMPLETION_PROTECTED_FIELDS = [
|
|
@@ -7599,8 +7583,10 @@ var init_cloud_router = __esm(() => {
|
|
|
7599
7583
|
function applyTodosCliAuthorityEnvironment(authority, env = process.env) {
|
|
7600
7584
|
if (authority.route !== "local" || authority.selected_by !== "local-only-command")
|
|
7601
7585
|
return;
|
|
7602
|
-
env.
|
|
7603
|
-
env.
|
|
7586
|
+
env.HASNA_TODOS_API_URL = "";
|
|
7587
|
+
env.HASNA_TODOS_API_KEY = "";
|
|
7588
|
+
env.TODOS_API_URL = "";
|
|
7589
|
+
env.TODOS_API_KEY = "";
|
|
7604
7590
|
}
|
|
7605
7591
|
function isTodosCliCommandVisibleForRoute(command, route, remoteCapabilities = new Set) {
|
|
7606
7592
|
if (route === "local")
|
|
@@ -7844,7 +7830,7 @@ function assertInvocationRoutable(invocation) {
|
|
|
7844
7830
|
if (command && !owner) {
|
|
7845
7831
|
const suggestions = nearestCommands(command);
|
|
7846
7832
|
const didYouMean = suggestions.length > 0 ? ` Did you mean: ${suggestions.join(", ")}?` : "";
|
|
7847
|
-
throw new Error(`UNKNOWN_COMMAND: \`${command}\` is not a built-in todos command on the /v1 route.${didYouMean} ` + "Run `todos --help` for the commands available here; verbs contributed by optional packages are local-only. " + "(This is not a connectivity
|
|
7833
|
+
throw new Error(`UNKNOWN_COMMAND: \`${command}\` is not a built-in todos command on the /v1 route.${didYouMean} ` + "Run `todos --help` for the commands available here; verbs contributed by optional packages are local-only. " + "(This is not a connectivity or credential problem.)");
|
|
7848
7834
|
}
|
|
7849
7835
|
return owner;
|
|
7850
7836
|
}
|
|
@@ -7861,7 +7847,20 @@ function assertRemoteCommandSupported(invocation, owner) {
|
|
|
7861
7847
|
}
|
|
7862
7848
|
}
|
|
7863
7849
|
function initializeTodosCliAuthority(args = process.argv.slice(2), env = process.env) {
|
|
7864
|
-
|
|
7850
|
+
let mode;
|
|
7851
|
+
try {
|
|
7852
|
+
mode = resolveTodosCliStorageMode(env);
|
|
7853
|
+
} catch (error) {
|
|
7854
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7855
|
+
if (message.includes("REMOTE_STORAGE_MODE_REMOVED"))
|
|
7856
|
+
throw error;
|
|
7857
|
+
const invocation2 = parseInvocation(args);
|
|
7858
|
+
if (isMetadataInvocation(args, invocation2)) {
|
|
7859
|
+
const status = getTodosRemoteAuthorityConfigStatus(env);
|
|
7860
|
+
return { route: "remote-diagnostic", v1_base_url: status.v1_base_url };
|
|
7861
|
+
}
|
|
7862
|
+
throw error;
|
|
7863
|
+
}
|
|
7865
7864
|
if (!mode.selected)
|
|
7866
7865
|
return { route: "local", v1_base_url: null };
|
|
7867
7866
|
const invocation = parseInvocation(args);
|
|
@@ -7876,7 +7875,7 @@ function initializeTodosCliAuthority(args = process.argv.slice(2), env = process
|
|
|
7876
7875
|
assertRemoteCommandSupported(invocation, owner);
|
|
7877
7876
|
const client = getTodosCloudClient(env);
|
|
7878
7877
|
if (!client) {
|
|
7879
|
-
throw new Error("REMOTE_API_UNAVAILABLE:
|
|
7878
|
+
throw new Error("REMOTE_API_UNAVAILABLE: HTTP routing did not resolve an authenticated /v1 client; local SQLite fallback is disabled");
|
|
7880
7879
|
}
|
|
7881
7880
|
return { route: "remote-http", v1_base_url: client.baseUrl };
|
|
7882
7881
|
}
|
|
@@ -12039,6 +12038,7 @@ __export(exports_config2, {
|
|
|
12039
12038
|
TODOS_STORAGE_FALLBACK_ENV: () => TODOS_STORAGE_FALLBACK_ENV,
|
|
12040
12039
|
TODOS_STORAGE_ENV: () => TODOS_STORAGE_ENV,
|
|
12041
12040
|
STORAGE_TABLES: () => STORAGE_TABLES,
|
|
12041
|
+
REMOVED_STORAGE_MODE_ENV_KEYS: () => REMOVED_STORAGE_MODE_ENV_KEYS,
|
|
12042
12042
|
CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV: () => CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV,
|
|
12043
12043
|
CANONICAL_TODOS_RDS_DATABASE: () => CANONICAL_TODOS_RDS_DATABASE,
|
|
12044
12044
|
CANONICAL_TODOS_RDS_CLUSTER_ENV: () => CANONICAL_TODOS_RDS_CLUSTER_ENV
|
|
@@ -12100,25 +12100,36 @@ function assertTodosRemoteStorageConfig(config) {
|
|
|
12100
12100
|
if (!isTodosPostgresBackend(config))
|
|
12101
12101
|
return;
|
|
12102
12102
|
if (!config.database?.url) {
|
|
12103
|
-
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when
|
|
12103
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when the postgresql backend is selected`);
|
|
12104
12104
|
}
|
|
12105
12105
|
}
|
|
12106
12106
|
function parseStorageBackend(value) {
|
|
12107
12107
|
const normalized = clean(value)?.toLowerCase();
|
|
12108
12108
|
if (!normalized)
|
|
12109
12109
|
return "sqlite";
|
|
12110
|
-
if (normalized === "sqlite"
|
|
12111
|
-
return
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12110
|
+
if (normalized === "sqlite")
|
|
12111
|
+
return "sqlite";
|
|
12112
|
+
if (normalized === "postgres" || normalized === "postgresql")
|
|
12113
|
+
return "postgres";
|
|
12114
|
+
if (["local", "remote", "cloud", "hybrid", "self_hosted"].includes(normalized)) {
|
|
12115
|
+
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.`);
|
|
12116
|
+
}
|
|
12117
|
+
throw new Error(`Storage backend must be sqlite or postgres`);
|
|
12116
12118
|
}
|
|
12117
12119
|
function parseStorageMode(value) {
|
|
12118
12120
|
return parseStorageBackend(value);
|
|
12119
12121
|
}
|
|
12120
12122
|
function getTodosStorageBackend(env = process.env) {
|
|
12121
|
-
|
|
12123
|
+
for (const key of REMOVED_STORAGE_MODE_ENV_KEYS) {
|
|
12124
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
12125
|
+
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.`);
|
|
12126
|
+
}
|
|
12127
|
+
}
|
|
12128
|
+
if (!getTodosStorageDatabaseUrl(env))
|
|
12129
|
+
return "sqlite";
|
|
12130
|
+
if (isTodosShadowEnabled(env))
|
|
12131
|
+
return "sqlite";
|
|
12132
|
+
return "postgres";
|
|
12122
12133
|
}
|
|
12123
12134
|
function getTodosStorageMode(env = process.env) {
|
|
12124
12135
|
return getTodosStorageBackend(env);
|
|
@@ -12192,7 +12203,7 @@ function parsePositiveInteger(value, fallback) {
|
|
|
12192
12203
|
}
|
|
12193
12204
|
return parsed;
|
|
12194
12205
|
}
|
|
12195
|
-
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"
|
|
12206
|
+
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";
|
|
12196
12207
|
var init_config2 = __esm(() => {
|
|
12197
12208
|
TODOS_STORAGE_TABLES = [
|
|
12198
12209
|
"todos_sync_records",
|
|
@@ -12200,7 +12211,6 @@ var init_config2 = __esm(() => {
|
|
|
12200
12211
|
];
|
|
12201
12212
|
STORAGE_TABLES = TODOS_STORAGE_TABLES;
|
|
12202
12213
|
TODOS_STORAGE_ENV = {
|
|
12203
|
-
mode: "HASNA_TODOS_STORAGE_MODE",
|
|
12204
12214
|
shadow: "HASNA_TODOS_SHADOW",
|
|
12205
12215
|
databaseUrl: "HASNA_TODOS_DATABASE_URL",
|
|
12206
12216
|
databaseSsl: "HASNA_TODOS_DATABASE_SSL",
|
|
@@ -12217,7 +12227,6 @@ var init_config2 = __esm(() => {
|
|
|
12217
12227
|
syncDryRun: "HASNA_TODOS_SYNC_DRY_RUN"
|
|
12218
12228
|
};
|
|
12219
12229
|
TODOS_STORAGE_FALLBACK_ENV = {
|
|
12220
|
-
mode: "TODOS_STORAGE_MODE",
|
|
12221
12230
|
shadow: "TODOS_SHADOW",
|
|
12222
12231
|
databaseUrl: "TODOS_DATABASE_URL",
|
|
12223
12232
|
databaseSsl: "TODOS_DATABASE_SSL",
|
|
@@ -12233,14 +12242,12 @@ var init_config2 = __esm(() => {
|
|
|
12233
12242
|
syncBatchSize: "TODOS_SYNC_BATCH_SIZE",
|
|
12234
12243
|
syncDryRun: "TODOS_SYNC_DRY_RUN"
|
|
12235
12244
|
};
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
cloud: "postgres"
|
|
12243
|
-
};
|
|
12245
|
+
REMOVED_STORAGE_MODE_ENV_KEYS = [
|
|
12246
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
12247
|
+
"HASNA_TODOS_MODE",
|
|
12248
|
+
"TODOS_STORAGE_MODE",
|
|
12249
|
+
"TODOS_MODE"
|
|
12250
|
+
];
|
|
12244
12251
|
});
|
|
12245
12252
|
|
|
12246
12253
|
// src/storage/shadow-outbox-schema.ts
|
|
@@ -15383,8 +15390,8 @@ var init_secret_redaction = __esm(() => {
|
|
|
15383
15390
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
15384
15391
|
DEFAULT_PATTERNS = [
|
|
15385
15392
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
15386
|
-
{ name: "github_pat", pattern: /\
|
|
15387
|
-
{ name: "github_oauth", pattern: /\
|
|
15393
|
+
{ name: "github_pat", pattern: /\bgh[p]_[a-zA-Z0-9]{20,}\b/g },
|
|
15394
|
+
{ name: "github_oauth", pattern: /\bgh[o]_[a-zA-Z0-9]{20,}\b/g },
|
|
15388
15395
|
{ name: "aws_access_key", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
15389
15396
|
{ name: "bearer_token", pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+=*\b/gi },
|
|
15390
15397
|
{ name: "jwt", pattern: /\beyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g },
|
|
@@ -15396,7 +15403,7 @@ var init_secret_redaction = __esm(() => {
|
|
|
15396
15403
|
/example\.com/i,
|
|
15397
15404
|
/your-api-key-here/i,
|
|
15398
15405
|
/sk-test/i,
|
|
15399
|
-
/
|
|
15406
|
+
/gh[p]_xxx/i
|
|
15400
15407
|
];
|
|
15401
15408
|
customRedactors = [];
|
|
15402
15409
|
});
|
|
@@ -31501,7 +31508,7 @@ function postgresTodosSyncSchemaSql(tableName = DEFAULT_TODOS_POSTGRES_SYNC_TABL
|
|
|
31501
31508
|
AS $$ SELECT unaccent('unaccent', $1) $$`,
|
|
31502
31509
|
`CREATE OR REPLACE FUNCTION todos_try_timestamptz(text)
|
|
31503
31510
|
RETURNS timestamptz
|
|
31504
|
-
LANGUAGE plpgsql IMMUTABLE PARALLEL
|
|
31511
|
+
LANGUAGE plpgsql IMMUTABLE PARALLEL UNSAFE
|
|
31505
31512
|
SET DateStyle TO 'ISO, YMD'
|
|
31506
31513
|
AS $$
|
|
31507
31514
|
BEGIN
|
|
@@ -36349,9 +36356,14 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
36349
36356
|
if (request.max_items !== 1) {
|
|
36350
36357
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_INVALID_BOUNDS", "max_items must be exactly 1 for terminal receipt lookup");
|
|
36351
36358
|
}
|
|
36352
|
-
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id
|
|
36359
|
+
if (request.authority !== "todos" || request.authority_id !== this.capabilityValue.authority_id || request.tenant_id !== this.capabilityValue.tenant_id) {
|
|
36353
36360
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_CAPABILITY_MISMATCH", "receipt lookup does not match this authority capability identity");
|
|
36354
36361
|
}
|
|
36362
|
+
requireString(request.corpus_id, "corpus_id", {
|
|
36363
|
+
min: 3,
|
|
36364
|
+
max: 128,
|
|
36365
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
36366
|
+
});
|
|
36355
36367
|
requireString(request.authority_route, "authority_route", {
|
|
36356
36368
|
min: 3,
|
|
36357
36369
|
max: 128,
|
|
@@ -36382,6 +36394,7 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
36382
36394
|
}
|
|
36383
36395
|
const receipt = await this.backend.getReceiptForLookup({
|
|
36384
36396
|
...authorityScope(this.capabilityValue),
|
|
36397
|
+
corpus_id: request.corpus_id,
|
|
36385
36398
|
route: request.authority_route,
|
|
36386
36399
|
package_version: request.package_version,
|
|
36387
36400
|
operation_id: request.operation_id,
|
|
@@ -36486,9 +36499,15 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
36486
36499
|
max: 128,
|
|
36487
36500
|
pattern: PACKAGE_VERSION_PATTERN
|
|
36488
36501
|
});
|
|
36502
|
+
requireString(sourceRequest.corpus_id, "corpus_id", {
|
|
36503
|
+
min: 3,
|
|
36504
|
+
max: 128,
|
|
36505
|
+
pattern: AUTHORITY_ROUTE_PATTERN
|
|
36506
|
+
});
|
|
36489
36507
|
assertForwardRequest(sourceRequest, {
|
|
36490
36508
|
...this.capabilityValue,
|
|
36491
|
-
package_version: sourceRequest.package_version
|
|
36509
|
+
package_version: sourceRequest.package_version,
|
|
36510
|
+
corpus_id: sourceRequest.corpus_id
|
|
36492
36511
|
});
|
|
36493
36512
|
const validation = await this.backend.transaction(async (transaction) => {
|
|
36494
36513
|
const storedSource = await transaction.getReceiptById(sourceReceipt.receipt_id);
|
|
@@ -36503,7 +36522,11 @@ class PackageOwnedTodosProjectRegistrationAuthority {
|
|
|
36503
36522
|
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)) {
|
|
36504
36523
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "receipt authority, operation, request, precondition, or normalized-call lineage changed");
|
|
36505
36524
|
}
|
|
36506
|
-
const binding = await transaction.getBinding(
|
|
36525
|
+
const binding = await transaction.getBinding({
|
|
36526
|
+
authority_id: sourceRequest.authority_id,
|
|
36527
|
+
tenant_id: sourceRequest.tenant_id,
|
|
36528
|
+
corpus_id: sourceRequest.corpus_id
|
|
36529
|
+
}, sourceRequest.resource_kind, sourceRequest.target_selector);
|
|
36507
36530
|
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) {
|
|
36508
36531
|
throw new TodosProjectRegistrationError("TODOS_PROJECT_REGISTRATION_ADOPTION_REJECTED", "accepted binding does not match the exact accepted receipt and source lineage");
|
|
36509
36532
|
}
|
|
@@ -55738,8 +55761,8 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
55738
55761
|
}
|
|
55739
55762
|
const created = await store.tasks.create(body2, storageContext);
|
|
55740
55763
|
const persisted = created?.id ? await store.tasks.get(created.id, storageContext) : null;
|
|
55741
|
-
if (!persisted || persisted.id !== created.id || (persisted.parent_id ?? null) !== (body2.parent_id ?? null) || (persisted.plan_id ?? null) !== (body2.plan_id ?? null)) {
|
|
55742
|
-
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
|
|
55764
|
+
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) {
|
|
55765
|
+
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" });
|
|
55743
55766
|
}
|
|
55744
55767
|
return json5({ task: persisted }, 201);
|
|
55745
55768
|
}
|
|
@@ -82428,7 +82451,7 @@ No task claimed (nothing available).`));
|
|
|
82428
82451
|
verdict_exit_code: verdict2.verdict,
|
|
82429
82452
|
fail_on_findings: verdict2.fail_on_findings,
|
|
82430
82453
|
dry_run: true,
|
|
82431
|
-
mode: "
|
|
82454
|
+
mode: "http",
|
|
82432
82455
|
authority: { v1_base_url: cloud.baseUrl, local_fallback: false },
|
|
82433
82456
|
routes: {
|
|
82434
82457
|
stats: true,
|
|
@@ -82650,7 +82673,7 @@ Findings`));
|
|
|
82650
82673
|
checks.push({ name: "Version", ok: true, message: `v${getPackageVersion3()} \xB7 remote HTTP client` });
|
|
82651
82674
|
const ok = checks.every((check) => check.ok);
|
|
82652
82675
|
if (opts.json || globalOpts.json) {
|
|
82653
|
-
console.log(JSON.stringify({ ok, mode: "
|
|
82676
|
+
console.log(JSON.stringify({ ok, mode: "http", checks }));
|
|
82654
82677
|
} else {
|
|
82655
82678
|
console.log(chalk9.bold(`todos health
|
|
82656
82679
|
`));
|
|
@@ -93376,7 +93399,7 @@ function getNativeStorageStatus(env = process.env) {
|
|
|
93376
93399
|
const remoteEnabled = isTodosPostgresBackend(config);
|
|
93377
93400
|
const remoteFieldsConfigured = Boolean(config.database || config.objectStorage);
|
|
93378
93401
|
if (!remoteEnabled && remoteFieldsConfigured) {
|
|
93379
|
-
warnings.push(`the sqlite backend
|
|
93402
|
+
warnings.push(`the sqlite backend ignores configured remote storage fields`);
|
|
93380
93403
|
}
|
|
93381
93404
|
if (remoteEnabled && !config.objectStorage) {
|
|
93382
93405
|
warnings.push(`${TODOS_STORAGE_ENV.s3Bucket} is not configured, so artifact sync will stay local`);
|
|
@@ -93469,7 +93492,7 @@ function storageEnvStatus(env) {
|
|
|
93469
93492
|
function fallbackConfig(env) {
|
|
93470
93493
|
let mode;
|
|
93471
93494
|
try {
|
|
93472
|
-
mode =
|
|
93495
|
+
mode = getTodosStorageBackend(env);
|
|
93473
93496
|
} catch {
|
|
93474
93497
|
mode = "sqlite";
|
|
93475
93498
|
}
|
package/dist/cli/stage-a.d.ts
CHANGED
|
@@ -18,7 +18,9 @@ export type TodosCliCommandOwner = "diagnostic" | "remote-http" | "local-only";
|
|
|
18
18
|
* mutating the caller's environment. The executable applies an admitted local
|
|
19
19
|
* redaction decision before importing command modules so any later
|
|
20
20
|
* `getTodosCloudClient()` call cannot reconstruct hosted routing from the
|
|
21
|
-
* ambient
|
|
21
|
+
* ambient API pair. The retired storage-mode variables are never written here —
|
|
22
|
+
* they are banned (owner directive 2026-08-15), and the HTTP selector is
|
|
23
|
+
* HASNA_TODOS_API_URL + HASNA_TODOS_API_KEY, which the redaction blanks.
|
|
22
24
|
*/
|
|
23
25
|
export declare function applyTodosCliAuthorityEnvironment(authority: TodosCliAuthorityInitialization, env?: Env): void;
|
|
24
26
|
export declare const TODOS_CLI_COMMAND_ALIASES: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAC1C,OAAO,EAKL,KAAK,4BAA4B,EAClC,MAAM,mBAAmB,CAAC;AAE3B,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,oBAAoB,CAAA;CAAE,GACzE;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAE/E;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,+BAA+B,EAC1C,GAAG,GAAE,GAAwB,GAC5B,IAAI,CAMN;AAyBD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAkFvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,GACxE,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,GACxE,IAAI,CAUN;AAED;;;;;;;;GAQG;AACH,wBAAgB,2CAA2C,CACzD,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,EACzE,IAAI,GAAE,SAAS,MAAM,EAAO,GAC3B,MAAM,GAAG,IAAI,CAYf;AA2XD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,GAAwB,GAC5B,+BAA+B,CAsCjC"}
|
package/dist/contracts.js
CHANGED
|
@@ -4177,6 +4177,7 @@ __export(exports_config, {
|
|
|
4177
4177
|
TODOS_STORAGE_FALLBACK_ENV: () => TODOS_STORAGE_FALLBACK_ENV,
|
|
4178
4178
|
TODOS_STORAGE_ENV: () => TODOS_STORAGE_ENV,
|
|
4179
4179
|
STORAGE_TABLES: () => STORAGE_TABLES,
|
|
4180
|
+
REMOVED_STORAGE_MODE_ENV_KEYS: () => REMOVED_STORAGE_MODE_ENV_KEYS,
|
|
4180
4181
|
CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV: () => CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV,
|
|
4181
4182
|
CANONICAL_TODOS_RDS_DATABASE: () => CANONICAL_TODOS_RDS_DATABASE,
|
|
4182
4183
|
CANONICAL_TODOS_RDS_CLUSTER_ENV: () => CANONICAL_TODOS_RDS_CLUSTER_ENV
|
|
@@ -4238,25 +4239,36 @@ function assertTodosRemoteStorageConfig(config) {
|
|
|
4238
4239
|
if (!isTodosPostgresBackend(config))
|
|
4239
4240
|
return;
|
|
4240
4241
|
if (!config.database?.url) {
|
|
4241
|
-
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when
|
|
4242
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when the postgresql backend is selected`);
|
|
4242
4243
|
}
|
|
4243
4244
|
}
|
|
4244
4245
|
function parseStorageBackend(value) {
|
|
4245
4246
|
const normalized = clean(value)?.toLowerCase();
|
|
4246
4247
|
if (!normalized)
|
|
4247
4248
|
return "sqlite";
|
|
4248
|
-
if (normalized === "sqlite"
|
|
4249
|
-
return
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4249
|
+
if (normalized === "sqlite")
|
|
4250
|
+
return "sqlite";
|
|
4251
|
+
if (normalized === "postgres" || normalized === "postgresql")
|
|
4252
|
+
return "postgres";
|
|
4253
|
+
if (["local", "remote", "cloud", "hybrid", "self_hosted"].includes(normalized)) {
|
|
4254
|
+
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.`);
|
|
4255
|
+
}
|
|
4256
|
+
throw new Error(`Storage backend must be sqlite or postgres`);
|
|
4254
4257
|
}
|
|
4255
4258
|
function parseStorageMode(value) {
|
|
4256
4259
|
return parseStorageBackend(value);
|
|
4257
4260
|
}
|
|
4258
4261
|
function getTodosStorageBackend(env = process.env) {
|
|
4259
|
-
|
|
4262
|
+
for (const key of REMOVED_STORAGE_MODE_ENV_KEYS) {
|
|
4263
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
4264
|
+
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.`);
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
if (!getTodosStorageDatabaseUrl(env))
|
|
4268
|
+
return "sqlite";
|
|
4269
|
+
if (isTodosShadowEnabled(env))
|
|
4270
|
+
return "sqlite";
|
|
4271
|
+
return "postgres";
|
|
4260
4272
|
}
|
|
4261
4273
|
function getTodosStorageMode(env = process.env) {
|
|
4262
4274
|
return getTodosStorageBackend(env);
|
|
@@ -4330,7 +4342,7 @@ function parsePositiveInteger(value, fallback) {
|
|
|
4330
4342
|
}
|
|
4331
4343
|
return parsed;
|
|
4332
4344
|
}
|
|
4333
|
-
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"
|
|
4345
|
+
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";
|
|
4334
4346
|
var init_config = __esm(() => {
|
|
4335
4347
|
TODOS_STORAGE_TABLES = [
|
|
4336
4348
|
"todos_sync_records",
|
|
@@ -4338,7 +4350,6 @@ var init_config = __esm(() => {
|
|
|
4338
4350
|
];
|
|
4339
4351
|
STORAGE_TABLES = TODOS_STORAGE_TABLES;
|
|
4340
4352
|
TODOS_STORAGE_ENV = {
|
|
4341
|
-
mode: "HASNA_TODOS_STORAGE_MODE",
|
|
4342
4353
|
shadow: "HASNA_TODOS_SHADOW",
|
|
4343
4354
|
databaseUrl: "HASNA_TODOS_DATABASE_URL",
|
|
4344
4355
|
databaseSsl: "HASNA_TODOS_DATABASE_SSL",
|
|
@@ -4355,7 +4366,6 @@ var init_config = __esm(() => {
|
|
|
4355
4366
|
syncDryRun: "HASNA_TODOS_SYNC_DRY_RUN"
|
|
4356
4367
|
};
|
|
4357
4368
|
TODOS_STORAGE_FALLBACK_ENV = {
|
|
4358
|
-
mode: "TODOS_STORAGE_MODE",
|
|
4359
4369
|
shadow: "TODOS_SHADOW",
|
|
4360
4370
|
databaseUrl: "TODOS_DATABASE_URL",
|
|
4361
4371
|
databaseSsl: "TODOS_DATABASE_SSL",
|
|
@@ -4371,14 +4381,12 @@ var init_config = __esm(() => {
|
|
|
4371
4381
|
syncBatchSize: "TODOS_SYNC_BATCH_SIZE",
|
|
4372
4382
|
syncDryRun: "TODOS_SYNC_DRY_RUN"
|
|
4373
4383
|
};
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
cloud: "postgres"
|
|
4381
|
-
};
|
|
4384
|
+
REMOVED_STORAGE_MODE_ENV_KEYS = [
|
|
4385
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
4386
|
+
"HASNA_TODOS_MODE",
|
|
4387
|
+
"TODOS_STORAGE_MODE",
|
|
4388
|
+
"TODOS_MODE"
|
|
4389
|
+
];
|
|
4382
4390
|
});
|
|
4383
4391
|
|
|
4384
4392
|
// src/storage/shadow-outbox-schema.ts
|
|
@@ -7227,8 +7235,8 @@ var init_secret_redaction = __esm(() => {
|
|
|
7227
7235
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
7228
7236
|
DEFAULT_PATTERNS = [
|
|
7229
7237
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
7230
|
-
{ name: "github_pat", pattern: /\
|
|
7231
|
-
{ name: "github_oauth", pattern: /\
|
|
7238
|
+
{ name: "github_pat", pattern: /\bgh[p]_[a-zA-Z0-9]{20,}\b/g },
|
|
7239
|
+
{ name: "github_oauth", pattern: /\bgh[o]_[a-zA-Z0-9]{20,}\b/g },
|
|
7232
7240
|
{ name: "aws_access_key", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
7233
7241
|
{ name: "bearer_token", pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+=*\b/gi },
|
|
7234
7242
|
{ name: "jwt", pattern: /\beyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g },
|
|
@@ -7240,7 +7248,7 @@ var init_secret_redaction = __esm(() => {
|
|
|
7240
7248
|
/example\.com/i,
|
|
7241
7249
|
/your-api-key-here/i,
|
|
7242
7250
|
/sk-test/i,
|
|
7243
|
-
/
|
|
7251
|
+
/gh[p]_xxx/i
|
|
7244
7252
|
];
|
|
7245
7253
|
customRedactors = [];
|
|
7246
7254
|
});
|
|
@@ -12720,7 +12728,7 @@ var init_tasks = __esm(() => {
|
|
|
12720
12728
|
// package.json
|
|
12721
12729
|
var package_default = {
|
|
12722
12730
|
name: "@hasna/todos",
|
|
12723
|
-
version: "0.15.
|
|
12731
|
+
version: "0.15.34",
|
|
12724
12732
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12725
12733
|
type: "module",
|
|
12726
12734
|
main: "dist/index.js",
|
|
@@ -12794,9 +12802,7 @@ var package_default = {
|
|
|
12794
12802
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
12795
12803
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
12796
12804
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
12797
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
12798
|
-
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
12799
|
-
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
12805
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
12800
12806
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
12801
12807
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
12802
12808
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|