@indecisivedev/openplan 0.2.0-alpha.2

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.
Files changed (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/access-policy.d.ts +35 -0
  4. package/dist/access-policy.js +107 -0
  5. package/dist/access-policy.js.map +1 -0
  6. package/dist/access-store.d.ts +33 -0
  7. package/dist/access-store.js +212 -0
  8. package/dist/access-store.js.map +1 -0
  9. package/dist/admin.d.ts +1 -0
  10. package/dist/admin.js +13 -0
  11. package/dist/admin.js.map +1 -0
  12. package/dist/api.d.ts +2 -0
  13. package/dist/api.js +867 -0
  14. package/dist/api.js.map +1 -0
  15. package/dist/bootstrap-admin.d.ts +1 -0
  16. package/dist/bootstrap-admin.js +35 -0
  17. package/dist/bootstrap-admin.js.map +1 -0
  18. package/dist/browser-security.d.ts +5 -0
  19. package/dist/browser-security.js +53 -0
  20. package/dist/browser-security.js.map +1 -0
  21. package/dist/celld-quickstart.d.ts +51 -0
  22. package/dist/celld-quickstart.js +1175 -0
  23. package/dist/celld-quickstart.js.map +1 -0
  24. package/dist/cli-api-client.d.ts +78 -0
  25. package/dist/cli-api-client.js +272 -0
  26. package/dist/cli-api-client.js.map +1 -0
  27. package/dist/cli-credentials.d.ts +47 -0
  28. package/dist/cli-credentials.js +447 -0
  29. package/dist/cli-credentials.js.map +1 -0
  30. package/dist/cli-endpoint.d.ts +19 -0
  31. package/dist/cli-endpoint.js +56 -0
  32. package/dist/cli-endpoint.js.map +1 -0
  33. package/dist/cli-program.d.ts +11 -0
  34. package/dist/cli-program.js +934 -0
  35. package/dist/cli-program.js.map +1 -0
  36. package/dist/cli.d.ts +2 -0
  37. package/dist/cli.js +7 -0
  38. package/dist/cli.js.map +1 -0
  39. package/dist/client-ip.d.ts +4 -0
  40. package/dist/client-ip.js +49 -0
  41. package/dist/client-ip.js.map +1 -0
  42. package/dist/config.d.ts +35 -0
  43. package/dist/config.js +113 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/crypto.d.ts +3 -0
  46. package/dist/crypto.js +11 -0
  47. package/dist/crypto.js.map +1 -0
  48. package/dist/database.d.ts +15 -0
  49. package/dist/database.js +155 -0
  50. package/dist/database.js.map +1 -0
  51. package/dist/db.d.ts +31 -0
  52. package/dist/db.js +388 -0
  53. package/dist/db.js.map +1 -0
  54. package/dist/drafts.d.ts +43 -0
  55. package/dist/drafts.js +90 -0
  56. package/dist/drafts.js.map +1 -0
  57. package/dist/feature-settings.d.ts +7 -0
  58. package/dist/feature-settings.js +32 -0
  59. package/dist/feature-settings.js.map +1 -0
  60. package/dist/generated/annotation-client.d.ts +1 -0
  61. package/dist/generated/annotation-client.js +2 -0
  62. package/dist/generated/annotation-client.js.map +1 -0
  63. package/dist/html-policy.d.ts +15 -0
  64. package/dist/html-policy.js +172 -0
  65. package/dist/html-policy.js.map +1 -0
  66. package/dist/ids.d.ts +2 -0
  67. package/dist/ids.js +10 -0
  68. package/dist/ids.js.map +1 -0
  69. package/dist/local-auth.d.ts +36 -0
  70. package/dist/local-auth.js +215 -0
  71. package/dist/local-auth.js.map +1 -0
  72. package/dist/maintenance.d.ts +1 -0
  73. package/dist/maintenance.js +18 -0
  74. package/dist/maintenance.js.map +1 -0
  75. package/dist/oidc.d.ts +39 -0
  76. package/dist/oidc.js +194 -0
  77. package/dist/oidc.js.map +1 -0
  78. package/dist/public-url.d.ts +17 -0
  79. package/dist/public-url.js +96 -0
  80. package/dist/public-url.js.map +1 -0
  81. package/dist/rate-limit.d.ts +25 -0
  82. package/dist/rate-limit.js +55 -0
  83. package/dist/rate-limit.js.map +1 -0
  84. package/dist/reconcile.d.ts +5 -0
  85. package/dist/reconcile.js +18 -0
  86. package/dist/reconcile.js.map +1 -0
  87. package/dist/render-annotations.d.ts +10 -0
  88. package/dist/render-annotations.js +73 -0
  89. package/dist/render-annotations.js.map +1 -0
  90. package/dist/render-web.d.ts +74 -0
  91. package/dist/render-web.js +439 -0
  92. package/dist/render-web.js.map +1 -0
  93. package/dist/render.d.ts +4 -0
  94. package/dist/render.js +85 -0
  95. package/dist/render.js.map +1 -0
  96. package/dist/server.d.ts +1 -0
  97. package/dist/server.js +26 -0
  98. package/dist/server.js.map +1 -0
  99. package/dist/shoo.d.ts +26 -0
  100. package/dist/shoo.js +92 -0
  101. package/dist/shoo.js.map +1 -0
  102. package/dist/sqlite-migrations.d.ts +6 -0
  103. package/dist/sqlite-migrations.js +214 -0
  104. package/dist/sqlite-migrations.js.map +1 -0
  105. package/dist/storage.d.ts +14 -0
  106. package/dist/storage.js +86 -0
  107. package/dist/storage.js.map +1 -0
  108. package/dist/types.d.ts +24 -0
  109. package/dist/types.js +2 -0
  110. package/dist/types.js.map +1 -0
  111. package/dist/upload-state.d.ts +19 -0
  112. package/dist/upload-state.js +118 -0
  113. package/dist/upload-state.js.map +1 -0
  114. package/dist/web-auth.d.ts +33 -0
  115. package/dist/web-auth.js +122 -0
  116. package/dist/web-auth.js.map +1 -0
  117. package/dist/web.d.ts +2 -0
  118. package/dist/web.js +550 -0
  119. package/dist/web.js.map +1 -0
  120. package/package.json +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 t3dotgg
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # Openplan
2
+
3
+ Openplan publishes authenticated static HTML drafts for agents and teams. This
4
+ source release includes a TypeScript CLI, a Node.js self-hosted runtime, and a
5
+ complete celld Worker project.
6
+
7
+ **New authenticated plans are private by default.** Public sharing is an explicit
8
+ owner choice; configure browser identity before expecting private reads. Existing
9
+ policies and historical legacy defaults are retained on upgrade.
10
+
11
+ Start with [Getting started](./docs/README.md). Agents can use
12
+ [`llms.txt`](./llms.txt) for setup paths, CLI commands, and verification steps.
13
+
14
+ ## Choose a deployment path
15
+
16
+ The alpha focuses on two deployment paths:
17
+
18
+ - **[Docker Compose on Linux — recommended first setup](./docs/self-hosted.md):**
19
+ run the app, SQLite, and SeaweedFS on one machine. The guide includes private
20
+ configuration generation, image builds, administrator bootstrap, browser
21
+ sign-in, and commands through the first verified upload and restart.
22
+ - **[Dedicated celld](./docs/celld.md):** install on an existing healthy fleet.
23
+ The quickstart supports celld 0.5.1 and the legacy 0.3.x/0.4.x paths, with
24
+ version-specific configuration. This does not provision the fleet itself.
25
+
26
+ The celld quickstart includes a neutral Wrangler configuration, protected
27
+ variable template, D1 migrations, reload/restart requirements, readiness
28
+ checks, bootstrap authentication, and a first upload. Do not deploy it onto a
29
+ shared fleet that already serves another application.
30
+
31
+ ## Install the CLI
32
+
33
+ The CLI alpha supports **Linux with Node.js 24.x**. macOS and Windows are not
34
+ supported yet; saved credentials require Linux's `/proc` filesystem. Deployment
35
+ guides below build from source. For an existing service, the planned npm channel
36
+ is `@indecisivedev/openplan@next`; once the public release is published, install it with:
37
+
38
+ ```sh
39
+ npm install --global @indecisivedev/openplan@next
40
+ openplan --version
41
+ openplan endpoint set https://openplan.example
42
+ openplan auth login
43
+ openplan whoami
44
+ ```
45
+
46
+ For a one-off invocation, use `npx --package=@indecisivedev/openplan@next openplan --help`.
47
+ Replace the example origin with your service. These commands describe the release
48
+ channel and do not establish that it is published. Before publication, use the
49
+ source build below. See [Connect the CLI](./docs/connect.md) for verification,
50
+ key enrollment, and the first upload.
51
+
52
+ The same CLI is also prepared for JSR as `@aarons7/openplan`. Once the alpha is
53
+ published, Linux users with Deno 2.9.6 can run:
54
+
55
+ ```sh
56
+ deno run -A jsr:@aarons7/openplan@0.2.0-alpha.2/cli --help
57
+ ```
58
+
59
+ See the [JSR CLI guide](https://github.com/aaronS7/openplan/blob/main/jsr/README.md) for permissions, setup and runtime
60
+ requirements. The source distribution includes both registry configurations;
61
+ these commands do not establish that either version has been published.
62
+
63
+ ## Build the source CLI
64
+
65
+ For a first installation, follow your deployment guide above in order; it
66
+ includes the required builds. These are the standalone source build checks:
67
+
68
+ [Node.js 24.x](https://nodejs.org/en/download) is the supported runtime for this
69
+ alpha. Other Node.js majors are outside the support scope. Confirm
70
+ `node --version` and `npm --version` before continuing.
71
+
72
+ ```sh
73
+ npm ci
74
+ npm run check
75
+ ```
76
+
77
+ Annotation bundles are reproducible from the included client code through
78
+ `npm run generate:annotations`.
79
+
80
+ ## Setup and publishing
81
+
82
+ - [Connect to an existing service](./docs/connect.md): install or build the CLI, select an
83
+ endpoint, authenticate, and verify a first upload.
84
+ - [Publish and update](./docs/publishing.md): static HTML sample, byte
85
+ verification, versions, and sharing.
86
+ - [CLI reference](./docs/cli.md) and [configuration](./docs/configuration.md):
87
+ exact commands and runtime-specific variables.
88
+ - [OpenID Connect](./docs/oidc.md): configure browser SSO with your identity provider.
89
+ - [Troubleshooting](./docs/troubleshooting.md): recover from a failed step.
90
+
91
+ ## CLI credentials and upgrades
92
+
93
+ CLI keys are bound to a canonical origin. Login uses masked TTY input;
94
+ noninteractive enrollment uses `auth set --stdin --api-url <origin>`, never a
95
+ positional key. Both verify fresh input and save only the binding. To also change
96
+ the default, run `endpoint set <origin>` separately; the former combined behavior
97
+ is intentionally removed. See [safe enrollment](./docs/cli.md#enroll-a-key-without-changing-the-default).
98
+
99
+ Environment keys require independently configured `OPENPLAN_API_KEY_ORIGIN`;
100
+ missing/mismatched binding fails without fallback. Default uploads require
101
+ authentication; anonymous upload is explicit. Older global keys remain inactive.
102
+ [Upgrade and re-enroll every client](./docs/troubleshooting.md#upgrade-and-re-enroll-older-clients)
103
+ and retire old writers before resuming jobs. These instructions do not claim a
104
+ live rollout or public release has been qualified or published.
105
+
106
+ ## Help and contributions
107
+
108
+ See [Contributing](./CONTRIBUTING.md) for installation reports, bug reports,
109
+ and proposed changes. Use [the security policy](./SECURITY.md) to report a
110
+ vulnerability privately.
111
+
112
+ ## Project lineage
113
+
114
+ Openplan is a fork of Postplan by Theo Browne. New interfaces use the Openplan
115
+ name, while some Postplan identifiers remain as deprecated compatibility
116
+ aliases. The upstream copyright notice is preserved in `LICENSE`.
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,35 @@
1
+ import type { Request } from "express";
2
+ export type AccessPolicyMode = "private" | "password" | "public";
3
+ export type ResolvedAccessMode = AccessPolicyMode | "authenticated";
4
+ export interface AccessPolicyRecord {
5
+ id: string;
6
+ mode: AccessPolicyMode;
7
+ password_algorithm: string | null;
8
+ password_iterations: number | null;
9
+ password_salt: string | null;
10
+ password_hash: string | null;
11
+ credential_revision: number;
12
+ }
13
+ export interface AccessPolicyView {
14
+ mode: ResolvedAccessMode;
15
+ inherited: boolean;
16
+ legacy: boolean;
17
+ passwordSet: boolean;
18
+ policyId: string | null;
19
+ credentialRevision: number | null;
20
+ }
21
+ export interface PasswordMaterial {
22
+ algorithm: "pbkdf2-sha256-v1";
23
+ iterations: number;
24
+ salt: string;
25
+ hash: string;
26
+ }
27
+ export declare function nodeLegacyAccessMode(): ResolvedAccessMode;
28
+ export declare function policyView(policy: AccessPolicyRecord | null, inherited: boolean, legacyMode: ResolvedAccessMode): AccessPolicyView;
29
+ export declare function derivePassword(password: string): PasswordMaterial;
30
+ export declare function verifyPassword(password: string, policy: AccessPolicyRecord): boolean;
31
+ export declare function createUnlockToken(policy: AccessPolicyRecord, draftId: string, versionId: string): string;
32
+ export declare function hasValidUnlock(req: Request, policy: AccessPolicyRecord, draftId: string, versionId: string, versionNumber?: number): boolean;
33
+ export declare function unlockCookie(token: string, draftId: string, versionNumber?: number): string;
34
+ export declare function unlockCookieName(draftId: string, versionNumber?: number): string;
35
+ export declare function requireShareSecret(): string;
@@ -0,0 +1,107 @@
1
+ import { pbkdf2Sync, randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { config } from "./config.js";
3
+ import { signToken, verifyToken } from "./web-auth.js";
4
+ const UNLOCK_TTL_SECONDS = 12 * 60 * 60;
5
+ export function nodeLegacyAccessMode() {
6
+ return "public";
7
+ }
8
+ export function policyView(policy, inherited, legacyMode) {
9
+ return {
10
+ mode: policy?.mode || legacyMode,
11
+ inherited,
12
+ legacy: !policy,
13
+ passwordSet: policy?.mode === "password" && Boolean(policy.password_hash),
14
+ policyId: policy?.id || null,
15
+ credentialRevision: policy?.credential_revision ?? null
16
+ };
17
+ }
18
+ export function derivePassword(password) {
19
+ const secret = requireShareSecret();
20
+ const salt = randomBytes(16).toString("base64url");
21
+ return {
22
+ algorithm: "pbkdf2-sha256-v1",
23
+ iterations: config.passwordIterations,
24
+ salt,
25
+ hash: passwordHash(password, secret, salt, config.passwordIterations)
26
+ };
27
+ }
28
+ export function verifyPassword(password, policy) {
29
+ if (password.length > 512 ||
30
+ policy.mode !== "password" ||
31
+ policy.password_algorithm !== "pbkdf2-sha256-v1" ||
32
+ !policy.password_iterations ||
33
+ !policy.password_salt ||
34
+ !policy.password_hash)
35
+ return false;
36
+ const actual = Buffer.from(passwordHash(password, requireShareSecret(), policy.password_salt, policy.password_iterations), "utf8");
37
+ const expected = Buffer.from(policy.password_hash, "utf8");
38
+ return actual.length === expected.length && timingSafeEqual(actual, expected);
39
+ }
40
+ export function createUnlockToken(policy, draftId, versionId) {
41
+ return signToken({
42
+ draftId,
43
+ versionId,
44
+ policyId: policy.id,
45
+ credentialRevision: policy.credential_revision
46
+ }, requireShareSecret(), UNLOCK_TTL_SECONDS);
47
+ }
48
+ export function hasValidUnlock(req, policy, draftId, versionId, versionNumber) {
49
+ const header = req.get("authorization") || "";
50
+ const headerMatch = header.match(/^Openplan-Share\s+(.+)$/i);
51
+ const token = headerMatch?.[1]?.trim() || readCookie(req, unlockCookieName(draftId, versionNumber));
52
+ const payload = token ? verifyToken(token, requireShareSecret()) : null;
53
+ return isUnlockPayload(payload) &&
54
+ payload.draftId === draftId &&
55
+ payload.versionId === versionId &&
56
+ payload.policyId === policy.id &&
57
+ payload.credentialRevision === policy.credential_revision;
58
+ }
59
+ export function unlockCookie(token, draftId, versionNumber) {
60
+ const attributes = [
61
+ `${unlockCookieName(draftId, versionNumber)}=${encodeURIComponent(token)}`,
62
+ "Path=/",
63
+ "HttpOnly",
64
+ "SameSite=Lax",
65
+ `Max-Age=${UNLOCK_TTL_SECONDS}`
66
+ ];
67
+ if (process.env.NODE_ENV !== "development")
68
+ attributes.push("Secure");
69
+ return attributes.join("; ");
70
+ }
71
+ export function unlockCookieName(draftId, versionNumber) {
72
+ return `openplan_unlock_${draftId}_${versionNumber === undefined ? "current" : `v${versionNumber}`}`;
73
+ }
74
+ export function requireShareSecret() {
75
+ if (!config.shareSecret)
76
+ throw new Error("OPENPLAN_SHARE_SECRET is not configured.");
77
+ return config.shareSecret;
78
+ }
79
+ function passwordHash(password, secret, salt, iterations) {
80
+ return pbkdf2Sync(`${password}\0${secret}`, Buffer.from(salt, "base64url"), iterations, 32, "sha256")
81
+ .toString("base64url");
82
+ }
83
+ function readCookie(req, name) {
84
+ const header = req.get("cookie") || "";
85
+ for (const part of header.split(";")) {
86
+ const separator = part.indexOf("=");
87
+ if (separator === -1 || part.slice(0, separator).trim() !== name)
88
+ continue;
89
+ try {
90
+ return decodeURIComponent(part.slice(separator + 1).trim());
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ function isUnlockPayload(value) {
99
+ if (!value || typeof value !== "object")
100
+ return false;
101
+ const payload = value;
102
+ return typeof payload.draftId === "string" &&
103
+ typeof payload.versionId === "string" &&
104
+ typeof payload.policyId === "string" &&
105
+ typeof payload.credentialRevision === "number";
106
+ }
107
+ //# sourceMappingURL=access-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-policy.js","sourceRoot":"","sources":["../src/access-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { DatabaseClient } from "./database.js";
2
+ import { type AccessPolicyMode, type AccessPolicyRecord, type AccessPolicyView, type ResolvedAccessMode } from "./access-policy.js";
3
+ export interface DraftAccessTarget {
4
+ draftId: string;
5
+ ownerAccountId: string;
6
+ title: string;
7
+ versionId: string;
8
+ versionNumber: number;
9
+ objectKey: string;
10
+ contentHash: string;
11
+ inherited: boolean;
12
+ policy: AccessPolicyRecord | null;
13
+ mode: ResolvedAccessMode;
14
+ }
15
+ export interface DraftAccessOverview {
16
+ plan: AccessPolicyView;
17
+ versions: Map<number, AccessPolicyView>;
18
+ }
19
+ export interface AccessMutationInput {
20
+ accountId: string;
21
+ apiKeyId?: string | null;
22
+ draftId: string;
23
+ versionNumber?: number;
24
+ mode?: AccessPolicyMode;
25
+ password?: string;
26
+ inherit?: boolean;
27
+ requestId?: string | null;
28
+ }
29
+ export declare function createDefaultPolicy(client: DatabaseClient, accountId: string, mode: AccessPolicyMode): Promise<string>;
30
+ export declare function findDraftAccessTarget(draftId: string, versionNumber?: number): Promise<DraftAccessTarget | null>;
31
+ export declare function canAccountReadDraft(accountId: string, ownerAccountId: string): Promise<boolean>;
32
+ export declare function getDraftAccessOverview(accountId: string, draftId: string): Promise<DraftAccessOverview | null>;
33
+ export declare function setAccessPolicy(input: AccessMutationInput): Promise<AccessPolicyView | null>;
@@ -0,0 +1,212 @@
1
+ import { derivePassword, nodeLegacyAccessMode, policyView } from "./access-policy.js";
2
+ import { newInternalId } from "./ids.js";
3
+ import { newEventId, pool, withTransaction } from "./db.js";
4
+ export async function createDefaultPolicy(client, accountId, mode) {
5
+ return insertPolicy(client, accountId, mode);
6
+ }
7
+ export async function findDraftAccessTarget(draftId, versionNumber) {
8
+ const versionClause = versionNumber === undefined
9
+ ? "v.id = d.current_version_id"
10
+ : "v.draft_id = d.id AND v.version_number = $2";
11
+ const values = versionNumber === undefined ? [draftId] : [draftId, versionNumber];
12
+ const result = await pool.query(`
13
+ SELECT d.id AS draft_id, d.account_id, d.title,
14
+ v.id AS version_id, v.version_number, v.object_key, v.content_hash,
15
+ v.access_policy_id AS version_policy_id,
16
+ COALESCE(v.access_policy_id, d.default_access_policy_id) AS effective_policy_id,
17
+ p.id AS policy_id, p.mode, p.password_algorithm,
18
+ p.password_iterations, p.password_salt, p.password_hash,
19
+ p.credential_revision
20
+ FROM drafts d
21
+ JOIN draft_versions v ON ${versionClause}
22
+ LEFT JOIN draft_access_policies p
23
+ ON p.id = COALESCE(v.access_policy_id, d.default_access_policy_id)
24
+ WHERE d.id = $1
25
+ AND d.deleted_at IS NULL
26
+ AND d.disabled_at IS NULL
27
+ AND v.status = 'ready'
28
+ LIMIT 1
29
+ `, values);
30
+ return mapTarget(result.rows[0]);
31
+ }
32
+ export async function canAccountReadDraft(accountId, ownerAccountId) {
33
+ if (accountId === ownerAccountId)
34
+ return true;
35
+ const result = await pool.query(`
36
+ SELECT 1 FROM account_access_grants g
37
+ JOIN api_keys grant_key ON grant_key.id = g.created_by_api_key_id
38
+ AND grant_key.revoked_at IS NULL AND grant_key.account_id = g.resource_account_id
39
+ WHERE viewer_account_id = $1 AND resource_account_id = $2
40
+ LIMIT 1
41
+ `, [accountId, ownerAccountId]);
42
+ return Boolean(result.rowCount);
43
+ }
44
+ export async function getDraftAccessOverview(accountId, draftId) {
45
+ const draft = await pool.query(`SELECT id, default_access_policy_id FROM drafts
46
+ WHERE id = $1 AND account_id = $2 AND deleted_at IS NULL LIMIT 1`, [draftId, accountId]);
47
+ const row = draft.rows[0];
48
+ if (!row)
49
+ return null;
50
+ const policies = await pool.query(`
51
+ SELECT CAST(NULL AS INTEGER) AS version_number, CAST(NULL AS TEXT) AS version_policy_id,
52
+ d.default_access_policy_id AS effective_policy_id,
53
+ p.id AS policy_id, p.mode, p.password_algorithm, p.password_iterations,
54
+ p.password_salt, p.password_hash, p.credential_revision
55
+ FROM drafts d
56
+ LEFT JOIN draft_access_policies p ON p.id = d.default_access_policy_id
57
+ WHERE d.id = $1
58
+ UNION ALL
59
+ SELECT v.version_number, v.access_policy_id AS version_policy_id,
60
+ COALESCE(v.access_policy_id, d.default_access_policy_id) AS effective_policy_id,
61
+ p.id AS policy_id, p.mode, p.password_algorithm, p.password_iterations,
62
+ p.password_salt, p.password_hash, p.credential_revision
63
+ FROM draft_versions v
64
+ JOIN drafts d ON d.id = v.draft_id
65
+ LEFT JOIN draft_access_policies p
66
+ ON p.id = COALESCE(v.access_policy_id, d.default_access_policy_id)
67
+ WHERE v.draft_id = $1 AND v.status = 'ready'
68
+ `, [draftId]);
69
+ const [planRow, ...versionRows] = policies.rows;
70
+ const planPolicy = policyFromRow(planRow);
71
+ const legacyMode = nodeLegacyAccessMode();
72
+ const versions = new Map();
73
+ for (const version of versionRows) {
74
+ if (version.version_number === null)
75
+ continue;
76
+ versions.set(Number(version.version_number), policyView(policyFromRow(version), version.version_policy_id === null, legacyMode));
77
+ }
78
+ return {
79
+ plan: policyView(planPolicy, false, legacyMode),
80
+ versions
81
+ };
82
+ }
83
+ export async function setAccessPolicy(input) {
84
+ return withTransaction(async (client) => {
85
+ const draft = await client.query(`SELECT id, account_id, default_access_policy_id FROM drafts
86
+ WHERE id = $1 AND account_id = $2 AND deleted_at IS NULL LIMIT 1`, [input.draftId, input.accountId]);
87
+ const owned = draft.rows[0];
88
+ if (!owned)
89
+ return null;
90
+ let versionId = null;
91
+ let previousPolicyId = owned.default_access_policy_id;
92
+ if (input.versionNumber !== undefined) {
93
+ const version = await client.query(`SELECT id, access_policy_id FROM draft_versions
94
+ WHERE draft_id = $1 AND version_number = $2 LIMIT 1`, [input.draftId, input.versionNumber]);
95
+ const versionRow = version.rows[0];
96
+ if (!versionRow)
97
+ return null;
98
+ versionId = versionRow.id;
99
+ previousPolicyId = versionRow.access_policy_id;
100
+ if (input.inherit) {
101
+ await client.query("UPDATE draft_versions SET access_policy_id = NULL WHERE id = $1", [versionId]);
102
+ const view = await currentPlanView(client, input.draftId, true);
103
+ await recordEvent(client, input, versionId, await modeForPolicy(client, previousPolicyId), view.mode, view.policyId, view.credentialRevision);
104
+ return view;
105
+ }
106
+ }
107
+ else if (input.inherit) {
108
+ throw new Error("Plan access cannot inherit.");
109
+ }
110
+ if (!input.mode)
111
+ throw new Error("Access mode is required.");
112
+ const previousPolicy = previousPolicyId ? await policyById(client, previousPolicyId) : null;
113
+ const credentialRevision = input.mode === "password" && previousPolicy?.mode === "password"
114
+ ? previousPolicy.credential_revision + 1
115
+ : 1;
116
+ const policyId = await insertPolicy(client, input.accountId, input.mode, input.password, credentialRevision);
117
+ if (versionId) {
118
+ await client.query("UPDATE draft_versions SET access_policy_id = $1 WHERE id = $2", [policyId, versionId]);
119
+ }
120
+ else {
121
+ await client.query("UPDATE drafts SET default_access_policy_id = $1, updated_at = now() WHERE id = $2", [policyId, input.draftId]);
122
+ }
123
+ const policy = await policyById(client, policyId);
124
+ const view = policyView(policy, false, nodeLegacyAccessMode());
125
+ await recordEvent(client, input, versionId, await modeForPolicy(client, previousPolicyId), view.mode, policyId, policy?.credential_revision ?? null);
126
+ return view;
127
+ });
128
+ }
129
+ async function insertPolicy(client, accountId, mode, password, credentialRevision = 1) {
130
+ if (mode === "password" && (!password || password.length < 8 || password.length > 512)) {
131
+ throw new Error("Password must be between 8 and 512 characters.");
132
+ }
133
+ const material = mode === "password" ? derivePassword(password) : null;
134
+ const id = newInternalId();
135
+ await client.query(`
136
+ INSERT INTO draft_access_policies (
137
+ id, mode, password_algorithm, password_iterations, password_salt,
138
+ password_hash, credential_revision, created_by_account_id
139
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
140
+ `, [
141
+ id,
142
+ mode,
143
+ material?.algorithm || null,
144
+ material?.iterations || null,
145
+ material?.salt || null,
146
+ material?.hash || null,
147
+ credentialRevision,
148
+ accountId
149
+ ]);
150
+ return id;
151
+ }
152
+ async function currentPlanView(client, draftId, inherited) {
153
+ const result = await client.query(`SELECT d.default_access_policy_id AS effective_policy_id, p.id AS policy_id, p.*
154
+ FROM drafts d LEFT JOIN draft_access_policies p ON p.id = d.default_access_policy_id WHERE d.id = $1`, [draftId]);
155
+ return policyView(policyFromRow(result.rows[0]), inherited, nodeLegacyAccessMode());
156
+ }
157
+ async function policyById(client, policyId) {
158
+ const result = await client.query("SELECT * FROM draft_access_policies WHERE id = $1 LIMIT 1", [policyId]);
159
+ return policyFromRow(result.rows[0]);
160
+ }
161
+ async function modeForPolicy(client, policyId) {
162
+ if (!policyId)
163
+ return null;
164
+ const result = await client.query("SELECT mode FROM draft_access_policies WHERE id = $1", [policyId]);
165
+ return result.rows[0]?.mode || null;
166
+ }
167
+ async function recordEvent(client, input, versionId, previousMode, newMode, policyId, credentialRevision) {
168
+ await client.query(`INSERT INTO access_policy_events (
169
+ id, draft_id, draft_version_id, actor_account_id, actor_api_key_id,
170
+ previous_mode, new_mode, policy_id, credential_revision, request_id
171
+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, [newEventId(), input.draftId, versionId, input.accountId, input.apiKeyId || null,
172
+ previousMode, newMode, policyId, credentialRevision, input.requestId || null]);
173
+ }
174
+ function mapTarget(row) {
175
+ if (!row)
176
+ return null;
177
+ const policy = policyFromRow(row);
178
+ return {
179
+ draftId: row.draft_id,
180
+ ownerAccountId: row.account_id,
181
+ title: row.title,
182
+ versionId: row.version_id,
183
+ versionNumber: Number(row.version_number),
184
+ objectKey: row.object_key,
185
+ contentHash: row.content_hash,
186
+ inherited: row.version_policy_id === null,
187
+ policy,
188
+ mode: policy?.mode || nodeLegacyAccessMode()
189
+ };
190
+ }
191
+ function policyFromRow(row) {
192
+ // Only an absent pointer is legacy. A broken explicit policy is not public.
193
+ if (typeof row?.effective_policy_id === "string" && (typeof row.policy_id !== "string" ||
194
+ (row.mode !== "private" && row.mode !== "password" && row.mode !== "public")))
195
+ throw new Error("Draft access policy is unavailable.");
196
+ if (!row || typeof row.policy_id !== "string" && typeof row.id !== "string")
197
+ return null;
198
+ const id = typeof row.policy_id === "string" ? row.policy_id : String(row.id);
199
+ if (row.mode !== "private" && row.mode !== "password" && row.mode !== "public")
200
+ return null;
201
+ return {
202
+ id,
203
+ mode: row.mode,
204
+ password_algorithm: typeof row.password_algorithm === "string" ? row.password_algorithm : null,
205
+ password_iterations: row.password_iterations === null || row.password_iterations === undefined
206
+ ? null : Number(row.password_iterations),
207
+ password_salt: typeof row.password_salt === "string" ? row.password_salt : null,
208
+ password_hash: typeof row.password_hash === "string" ? row.password_hash : null,
209
+ credential_revision: Number(row.credential_revision || 1)
210
+ };
211
+ }
212
+ //# sourceMappingURL=access-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"access-store.js","sourceRoot":"","sources":["../src/access-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function isAdminAccount(accountId: string | undefined | null): Promise<boolean>;
package/dist/admin.js ADDED
@@ -0,0 +1,13 @@
1
+ import { config } from "./config.js";
2
+ import { pool } from "./db.js";
3
+ export async function isAdminAccount(accountId) {
4
+ if (!accountId)
5
+ return false;
6
+ if (config.adminAccountIds.includes(accountId))
7
+ return true;
8
+ if (config.runtimeProfile !== "self-hosted")
9
+ return false;
10
+ const result = await pool.query("SELECT is_admin FROM accounts WHERE id = $1 LIMIT 1", [accountId]);
11
+ return Boolean(result.rows[0]?.is_admin);
12
+ }
13
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,SAAoC;IACvE,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,IAAI,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,IAAI,MAAM,CAAC,cAAc,KAAK,aAAa;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,qDAAqD,EACrD,CAAC,SAAS,CAAC,CACZ,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
package/dist/api.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { Application } from "express";
2
+ export declare function createApp(): Application;