@rewind-ai/cli 0.6.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.
- package/.env.example +8 -0
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/src/action/capture.d.ts +15 -0
- package/dist/src/action/capture.js +215 -0
- package/dist/src/action/capture.js.map +1 -0
- package/dist/src/action/mediate.d.ts +28 -0
- package/dist/src/action/mediate.js +109 -0
- package/dist/src/action/mediate.js.map +1 -0
- package/dist/src/action/mutate.d.ts +11 -0
- package/dist/src/action/mutate.js +189 -0
- package/dist/src/action/mutate.js.map +1 -0
- package/dist/src/action/objects.d.ts +5 -0
- package/dist/src/action/objects.js +50 -0
- package/dist/src/action/objects.js.map +1 -0
- package/dist/src/action/store.d.ts +24 -0
- package/dist/src/action/store.js +149 -0
- package/dist/src/action/store.js.map +1 -0
- package/dist/src/action/types.d.ts +84 -0
- package/dist/src/action/types.js +3 -0
- package/dist/src/action/types.js.map +1 -0
- package/dist/src/action/undo.d.ts +11 -0
- package/dist/src/action/undo.js +42 -0
- package/dist/src/action/undo.js.map +1 -0
- package/dist/src/adapters/filesystem.d.ts +35 -0
- package/dist/src/adapters/filesystem.js +499 -0
- package/dist/src/adapters/filesystem.js.map +1 -0
- package/dist/src/adapters/index.d.ts +7 -0
- package/dist/src/adapters/index.js +19 -0
- package/dist/src/adapters/index.js.map +1 -0
- package/dist/src/adapters/types.d.ts +54 -0
- package/dist/src/adapters/types.js +7 -0
- package/dist/src/adapters/types.js.map +1 -0
- package/dist/src/api/server.d.ts +25 -0
- package/dist/src/api/server.js +786 -0
- package/dist/src/api/server.js.map +1 -0
- package/dist/src/approval/store.d.ts +35 -0
- package/dist/src/approval/store.js +113 -0
- package/dist/src/approval/store.js.map +1 -0
- package/dist/src/checkpoint.d.ts +9 -0
- package/dist/src/checkpoint.js +140 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/cli/v5.d.ts +15 -0
- package/dist/src/cli/v5.js +110 -0
- package/dist/src/cli/v5.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +823 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/clients/types.d.ts +90 -0
- package/dist/src/clients/types.js +239 -0
- package/dist/src/clients/types.js.map +1 -0
- package/dist/src/commercial/auth/provider.d.ts +61 -0
- package/dist/src/commercial/auth/provider.js +227 -0
- package/dist/src/commercial/auth/provider.js.map +1 -0
- package/dist/src/commercial/entitlement/provider.d.ts +27 -0
- package/dist/src/commercial/entitlement/provider.js +192 -0
- package/dist/src/commercial/entitlement/provider.js.map +1 -0
- package/dist/src/commercial/entitlement/signing.d.ts +61 -0
- package/dist/src/commercial/entitlement/signing.js +124 -0
- package/dist/src/commercial/entitlement/signing.js.map +1 -0
- package/dist/src/commercial/env.d.ts +10 -0
- package/dist/src/commercial/env.js +40 -0
- package/dist/src/commercial/env.js.map +1 -0
- package/dist/src/commercial/product.d.ts +26 -0
- package/dist/src/commercial/product.js +39 -0
- package/dist/src/commercial/product.js.map +1 -0
- package/dist/src/commercial/store.d.ts +46 -0
- package/dist/src/commercial/store.js +104 -0
- package/dist/src/commercial/store.js.map +1 -0
- package/dist/src/commercial/stripe/checkout.d.ts +104 -0
- package/dist/src/commercial/stripe/checkout.js +469 -0
- package/dist/src/commercial/stripe/checkout.js.map +1 -0
- package/dist/src/core/compatibility.d.ts +15 -0
- package/dist/src/core/compatibility.js +226 -0
- package/dist/src/core/compatibility.js.map +1 -0
- package/dist/src/core/engine.d.ts +33 -0
- package/dist/src/core/engine.js +432 -0
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/lifecycle.d.ts +17 -0
- package/dist/src/core/lifecycle.js +56 -0
- package/dist/src/core/lifecycle.js.map +1 -0
- package/dist/src/core/types.d.ts +140 -0
- package/dist/src/core/types.js +37 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/destroy.d.ts +21 -0
- package/dist/src/destroy.js +219 -0
- package/dist/src/destroy.js.map +1 -0
- package/dist/src/diff.d.ts +13 -0
- package/dist/src/diff.js +251 -0
- package/dist/src/diff.js.map +1 -0
- package/dist/src/enforcement/detect.d.ts +13 -0
- package/dist/src/enforcement/detect.js +75 -0
- package/dist/src/enforcement/detect.js.map +1 -0
- package/dist/src/enforcement/hook-policy.d.ts +38 -0
- package/dist/src/enforcement/hook-policy.js +111 -0
- package/dist/src/enforcement/hook-policy.js.map +1 -0
- package/dist/src/enforcement/index.d.ts +8 -0
- package/dist/src/enforcement/index.js +8 -0
- package/dist/src/enforcement/index.js.map +1 -0
- package/dist/src/enforcement/perf.d.ts +6 -0
- package/dist/src/enforcement/perf.js +18 -0
- package/dist/src/enforcement/perf.js.map +1 -0
- package/dist/src/enforcement/policy.d.ts +12 -0
- package/dist/src/enforcement/policy.js +84 -0
- package/dist/src/enforcement/policy.js.map +1 -0
- package/dist/src/enforcement/readonly.d.ts +17 -0
- package/dist/src/enforcement/readonly.js +124 -0
- package/dist/src/enforcement/readonly.js.map +1 -0
- package/dist/src/enforcement/sandbox-clone.d.ts +6 -0
- package/dist/src/enforcement/sandbox-clone.js +11 -0
- package/dist/src/enforcement/sandbox-clone.js.map +1 -0
- package/dist/src/enforcement/setup.d.ts +33 -0
- package/dist/src/enforcement/setup.js +168 -0
- package/dist/src/enforcement/setup.js.map +1 -0
- package/dist/src/enforcement/trust.d.ts +10 -0
- package/dist/src/enforcement/trust.js +71 -0
- package/dist/src/enforcement/trust.js.map +1 -0
- package/dist/src/enforcement/types.d.ts +40 -0
- package/dist/src/enforcement/types.js +3 -0
- package/dist/src/enforcement/types.js.map +1 -0
- package/dist/src/entitlement/provider.d.ts +48 -0
- package/dist/src/entitlement/provider.js +95 -0
- package/dist/src/entitlement/provider.js.map +1 -0
- package/dist/src/hash.d.ts +9 -0
- package/dist/src/hash.js +23 -0
- package/dist/src/hash.js.map +1 -0
- package/dist/src/ledger/query.d.ts +19 -0
- package/dist/src/ledger/query.js +158 -0
- package/dist/src/ledger/query.js.map +1 -0
- package/dist/src/manifest.d.ts +32 -0
- package/dist/src/manifest.js +242 -0
- package/dist/src/manifest.js.map +1 -0
- package/dist/src/mcp/server.d.ts +7 -0
- package/dist/src/mcp/server.js +364 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/paths.d.ts +94 -0
- package/dist/src/paths.js +354 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/permission/engine.d.ts +15 -0
- package/dist/src/permission/engine.js +147 -0
- package/dist/src/permission/engine.js.map +1 -0
- package/dist/src/permission/types.d.ts +42 -0
- package/dist/src/permission/types.js +3 -0
- package/dist/src/permission/types.js.map +1 -0
- package/dist/src/product/setup.d.ts +35 -0
- package/dist/src/product/setup.js +300 -0
- package/dist/src/product/setup.js.map +1 -0
- package/dist/src/protect/audit.d.ts +5 -0
- package/dist/src/protect/audit.js +26 -0
- package/dist/src/protect/audit.js.map +1 -0
- package/dist/src/protect/capture.d.ts +7 -0
- package/dist/src/protect/capture.js +250 -0
- package/dist/src/protect/capture.js.map +1 -0
- package/dist/src/protect/fingerprint.d.ts +4 -0
- package/dist/src/protect/fingerprint.js +49 -0
- package/dist/src/protect/fingerprint.js.map +1 -0
- package/dist/src/protect/hook-cli.d.ts +2 -0
- package/dist/src/protect/hook-cli.js +107 -0
- package/dist/src/protect/hook-cli.js.map +1 -0
- package/dist/src/protect/index.d.ts +12 -0
- package/dist/src/protect/index.js +12 -0
- package/dist/src/protect/index.js.map +1 -0
- package/dist/src/protect/install.d.ts +34 -0
- package/dist/src/protect/install.js +293 -0
- package/dist/src/protect/install.js.map +1 -0
- package/dist/src/protect/intercept.d.ts +11 -0
- package/dist/src/protect/intercept.js +390 -0
- package/dist/src/protect/intercept.js.map +1 -0
- package/dist/src/protect/protect.d.ts +17 -0
- package/dist/src/protect/protect.js +194 -0
- package/dist/src/protect/protect.js.map +1 -0
- package/dist/src/protect/root-paths.d.ts +13 -0
- package/dist/src/protect/root-paths.js +140 -0
- package/dist/src/protect/root-paths.js.map +1 -0
- package/dist/src/protect/shell-policy.d.ts +17 -0
- package/dist/src/protect/shell-policy.js +269 -0
- package/dist/src/protect/shell-policy.js.map +1 -0
- package/dist/src/protect/status.d.ts +11 -0
- package/dist/src/protect/status.js +165 -0
- package/dist/src/protect/status.js.map +1 -0
- package/dist/src/protect/store.d.ts +20 -0
- package/dist/src/protect/store.js +170 -0
- package/dist/src/protect/store.js.map +1 -0
- package/dist/src/protect/types.d.ts +116 -0
- package/dist/src/protect/types.js +3 -0
- package/dist/src/protect/types.js.map +1 -0
- package/dist/src/protect/undo-session.d.ts +14 -0
- package/dist/src/protect/undo-session.js +182 -0
- package/dist/src/protect/undo-session.js.map +1 -0
- package/dist/src/restore.d.ts +39 -0
- package/dist/src/restore.js +141 -0
- package/dist/src/restore.js.map +1 -0
- package/dist/src/sandbox.d.ts +23 -0
- package/dist/src/sandbox.js +198 -0
- package/dist/src/sandbox.js.map +1 -0
- package/dist/src/session/ambient.d.ts +10 -0
- package/dist/src/session/ambient.js +53 -0
- package/dist/src/session/ambient.js.map +1 -0
- package/dist/src/session/attribution.d.ts +27 -0
- package/dist/src/session/attribution.js +201 -0
- package/dist/src/session/attribution.js.map +1 -0
- package/dist/src/session/index.d.ts +25 -0
- package/dist/src/session/index.js +472 -0
- package/dist/src/session/index.js.map +1 -0
- package/dist/src/session/process.d.ts +34 -0
- package/dist/src/session/process.js +234 -0
- package/dist/src/session/process.js.map +1 -0
- package/dist/src/session/store.d.ts +14 -0
- package/dist/src/session/store.js +125 -0
- package/dist/src/session/store.js.map +1 -0
- package/dist/src/session/types.d.ts +111 -0
- package/dist/src/session/types.js +3 -0
- package/dist/src/session/types.js.map +1 -0
- package/dist/src/session/watcher.d.ts +32 -0
- package/dist/src/session/watcher.js +186 -0
- package/dist/src/session/watcher.js.map +1 -0
- package/dist/src/timing.d.ts +7 -0
- package/dist/src/timing.js +19 -0
- package/dist/src/timing.js.map +1 -0
- package/dist/src/types.d.ts +101 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/verify.d.ts +8 -0
- package/dist/src/verify.js +126 -0
- package/dist/src/verify.js.map +1 -0
- package/docs/ADAPTERS.md +37 -0
- package/docs/APPROVALS.md +32 -0
- package/docs/ARCHITECTURE.md +57 -0
- package/docs/ATTRIBUTION.md +179 -0
- package/docs/COMMERCIAL.md +51 -0
- package/docs/CURSOR-ENFORCEMENT.md +73 -0
- package/docs/ENFORCEMENT.md +134 -0
- package/docs/FUTURE.md +91 -0
- package/docs/HUMAN-SETUP.md +98 -0
- package/docs/IDENTITY-AUTHORITY.md +35 -0
- package/docs/MCP.md +107 -0
- package/docs/PACKAGING.md +77 -0
- package/docs/PERMISSIONS.md +53 -0
- package/docs/PRODUCT-V5.md +63 -0
- package/docs/PRODUCT-V6.md +69 -0
- package/docs/PROTECTED-SESSIONS.md +155 -0
- package/docs/THREAT-MODEL.md +84 -0
- package/docs/TRANSACTIONS.md +57 -0
- package/package.json +85 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load local REWIND env (never commit secrets).
|
|
3
|
+
* Safe to call multiple times; loads once per process.
|
|
4
|
+
*
|
|
5
|
+
* Search order (first existing wins; does not override existing process.env):
|
|
6
|
+
* 1. process.cwd()/.env
|
|
7
|
+
* 2. ~/.rewind/.env (preferred for global npm installs)
|
|
8
|
+
* 3. package-adjacent .env (dev checkout only)
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadRewindEnv(): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load local REWIND env (never commit secrets).
|
|
3
|
+
* Safe to call multiple times; loads once per process.
|
|
4
|
+
*
|
|
5
|
+
* Search order (first existing wins; does not override existing process.env):
|
|
6
|
+
* 1. process.cwd()/.env
|
|
7
|
+
* 2. ~/.rewind/.env (preferred for global npm installs)
|
|
8
|
+
* 3. package-adjacent .env (dev checkout only)
|
|
9
|
+
*/
|
|
10
|
+
import { config } from "dotenv";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import os from "node:os";
|
|
15
|
+
let loaded = false;
|
|
16
|
+
export function loadRewindEnv() {
|
|
17
|
+
if (loaded)
|
|
18
|
+
return;
|
|
19
|
+
loaded = true;
|
|
20
|
+
// Unit tests set process.env explicitly — never pull a developer .env into CI/tests.
|
|
21
|
+
if (process.env.VITEST === "true" || process.env.REWIND_SKIP_DOTENV === "1") {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
25
|
+
const candidates = [
|
|
26
|
+
path.resolve(process.cwd(), ".env"),
|
|
27
|
+
path.join(os.homedir(), ".rewind", ".env"),
|
|
28
|
+
path.resolve(here, "../../.env"), // src/commercial → repo root
|
|
29
|
+
path.resolve(here, "../../../.env"), // dist/src/commercial → repo root
|
|
30
|
+
];
|
|
31
|
+
for (const file of candidates) {
|
|
32
|
+
if (existsSync(file)) {
|
|
33
|
+
config({ path: file, override: false });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// process.env may already be set by the shell / CI
|
|
38
|
+
config({ override: false });
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/commercial/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB,MAAM,UAAU,aAAa;IAC3B,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,GAAG,IAAI,CAAC;IAEd,qFAAqF;IACrF,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,KAAK,GAAG,EAAE,CAAC;QAC5E,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,6BAA6B;QAC/D,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,kCAAkC;KACxE,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACxC,OAAO;QACT,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,MAAM,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REWIND Personal — commercial product constants.
|
|
3
|
+
* Pricing is documented here for humans; never used as authority in Core.
|
|
4
|
+
* Stripe Price IDs come from environment variables.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PRODUCT_NAME = "REWIND Personal";
|
|
7
|
+
export declare const PRODUCT_POSITIONING = "Undo for AI agents.";
|
|
8
|
+
export declare const LIST_PRICE_GBP_MONTHLY = "2.99";
|
|
9
|
+
export declare const LIST_CURRENCY = "GBP";
|
|
10
|
+
/** Feature matrix — configurable launch limits. */
|
|
11
|
+
export interface PlanFeatures {
|
|
12
|
+
plan: "free" | "personal" | "development";
|
|
13
|
+
/** New mediated mutations allowed. */
|
|
14
|
+
allowNewMediation: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* INVARIANT: always true for locally recorded transactions.
|
|
17
|
+
* Never gate undo of already-captured work on payment.
|
|
18
|
+
*/
|
|
19
|
+
allowUndoExisting: true;
|
|
20
|
+
/** Soft limit for free tier (-1 = unlimited). */
|
|
21
|
+
maxMediatedActionsPerDay: number;
|
|
22
|
+
label: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const PLAN_MATRIX: Record<PlanFeatures["plan"], PlanFeatures>;
|
|
25
|
+
/** Recommended launch: free demonstrates magic; Personal is unlimited ongoing use. */
|
|
26
|
+
export declare const LAUNCH_NOTES: string[];
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* REWIND Personal — commercial product constants.
|
|
3
|
+
* Pricing is documented here for humans; never used as authority in Core.
|
|
4
|
+
* Stripe Price IDs come from environment variables.
|
|
5
|
+
*/
|
|
6
|
+
export const PRODUCT_NAME = "REWIND Personal";
|
|
7
|
+
export const PRODUCT_POSITIONING = "Undo for AI agents.";
|
|
8
|
+
export const LIST_PRICE_GBP_MONTHLY = "2.99";
|
|
9
|
+
export const LIST_CURRENCY = "GBP";
|
|
10
|
+
export const PLAN_MATRIX = {
|
|
11
|
+
development: {
|
|
12
|
+
plan: "development",
|
|
13
|
+
allowNewMediation: true,
|
|
14
|
+
allowUndoExisting: true,
|
|
15
|
+
maxMediatedActionsPerDay: -1,
|
|
16
|
+
label: "Development build",
|
|
17
|
+
},
|
|
18
|
+
free: {
|
|
19
|
+
plan: "free",
|
|
20
|
+
allowNewMediation: true,
|
|
21
|
+
allowUndoExisting: true,
|
|
22
|
+
maxMediatedActionsPerDay: 100,
|
|
23
|
+
label: "Free / trial",
|
|
24
|
+
},
|
|
25
|
+
personal: {
|
|
26
|
+
plan: "personal",
|
|
27
|
+
allowNewMediation: true,
|
|
28
|
+
allowUndoExisting: true,
|
|
29
|
+
maxMediatedActionsPerDay: -1,
|
|
30
|
+
label: "REWIND Personal",
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/** Recommended launch: free demonstrates magic; Personal is unlimited ongoing use. */
|
|
34
|
+
export const LAUNCH_NOTES = [
|
|
35
|
+
"Free/trial: full mediate → see transaction → undo demonstration (daily soft cap).",
|
|
36
|
+
"Personal (£2.99/mo): unlimited mediated actions for serious ongoing use.",
|
|
37
|
+
"CRITICAL: expired/cancelled subscription NEVER blocks undo of already-recorded transactions.",
|
|
38
|
+
];
|
|
39
|
+
//# sourceMappingURL=product.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.js","sourceRoot":"","sources":["../../../src/commercial/product.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAC9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AACzD,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC;AAC7C,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC;AAiBnC,MAAM,CAAC,MAAM,WAAW,GAA+C;IACrE,WAAW,EAAE;QACX,IAAI,EAAE,aAAa;QACnB,iBAAiB,EAAE,IAAI;QACvB,iBAAiB,EAAE,IAAI;QACvB,wBAAwB,EAAE,CAAC,CAAC;QAC5B,KAAK,EAAE,mBAAmB;KAC3B;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,iBAAiB,EAAE,IAAI;QACvB,iBAAiB,EAAE,IAAI;QACvB,wBAAwB,EAAE,GAAG;QAC7B,KAAK,EAAE,cAAc;KACtB;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,iBAAiB,EAAE,IAAI;QACvB,iBAAiB,EAAE,IAAI;QACvB,wBAAwB,EAAE,CAAC,CAAC;QAC5B,KAAK,EAAE,iBAAiB;KACzB;CACF,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,mFAAmF;IACnF,0EAA0E;IAC1E,8FAA8F;CAC/F,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local commercial data store (file-based — NOT Postgres).
|
|
3
|
+
* Holds only identity/billing/entitlement metadata.
|
|
4
|
+
* NEVER stores project files, before/after contents, or source code.
|
|
5
|
+
*/
|
|
6
|
+
export interface CommercialUser {
|
|
7
|
+
id: string;
|
|
8
|
+
email: string;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
stripeCustomerId: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface Installation {
|
|
13
|
+
id: string;
|
|
14
|
+
userId: string;
|
|
15
|
+
hostname: string;
|
|
16
|
+
platform: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
lastSeenAt: string;
|
|
19
|
+
}
|
|
20
|
+
export type SubscriptionStatus = "none" | "trialing" | "active" | "past_due" | "canceled" | "unpaid";
|
|
21
|
+
export interface SubscriptionRecord {
|
|
22
|
+
id: string;
|
|
23
|
+
userId: string;
|
|
24
|
+
status: SubscriptionStatus;
|
|
25
|
+
plan: "free" | "personal";
|
|
26
|
+
stripeSubscriptionId: string | null;
|
|
27
|
+
stripePriceId: string | null;
|
|
28
|
+
currentPeriodEnd: string | null;
|
|
29
|
+
cancelAtPeriodEnd: boolean;
|
|
30
|
+
updatedAt: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CommercialStore {
|
|
33
|
+
users: CommercialUser[];
|
|
34
|
+
installations: Installation[];
|
|
35
|
+
subscriptions: SubscriptionRecord[];
|
|
36
|
+
/** Processed Stripe event ids for idempotency */
|
|
37
|
+
processedStripeEvents: string[];
|
|
38
|
+
}
|
|
39
|
+
export declare function commercialDataDir(override?: string | undefined): string;
|
|
40
|
+
export declare function loadStore(dir?: string): Promise<CommercialStore>;
|
|
41
|
+
export declare function saveStore(store: CommercialStore, dir?: string): Promise<void>;
|
|
42
|
+
export declare function appendEntitlementEvent(event: Record<string, unknown>, dir?: string): Promise<void>;
|
|
43
|
+
export declare function newId(prefix: string): string;
|
|
44
|
+
export declare function upsertUserByEmail(email: string, dir?: string): Promise<CommercialUser>;
|
|
45
|
+
export declare function registerInstallation(userId: string, dir?: string): Promise<Installation>;
|
|
46
|
+
export declare function getSubscriptionForUser(userId: string, dir?: string): Promise<SubscriptionRecord | null>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local commercial data store (file-based — NOT Postgres).
|
|
3
|
+
* Holds only identity/billing/entitlement metadata.
|
|
4
|
+
* NEVER stores project files, before/after contents, or source code.
|
|
5
|
+
*/
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import { mkdir, readFile, writeFile, rename, appendFile } from "node:fs/promises";
|
|
9
|
+
import { randomBytes } from "node:crypto";
|
|
10
|
+
import { getUserRewindDir } from "../paths.js";
|
|
11
|
+
function defaultStore() {
|
|
12
|
+
return {
|
|
13
|
+
users: [],
|
|
14
|
+
installations: [],
|
|
15
|
+
subscriptions: [],
|
|
16
|
+
processedStripeEvents: [],
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function commercialDataDir(override = process.env.REWIND_COMMERCIAL_DIR) {
|
|
20
|
+
if (override)
|
|
21
|
+
return path.resolve(override);
|
|
22
|
+
return path.join(getUserRewindDir(), "commercial");
|
|
23
|
+
}
|
|
24
|
+
function storePath(dir) {
|
|
25
|
+
return path.join(dir, "store.json");
|
|
26
|
+
}
|
|
27
|
+
async function writeJsonAtomic(file, data) {
|
|
28
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
29
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
30
|
+
await writeFile(tmp, JSON.stringify(data, null, 2) + "\n", { mode: 0o600 });
|
|
31
|
+
await rename(tmp, file);
|
|
32
|
+
}
|
|
33
|
+
export async function loadStore(dir = commercialDataDir()) {
|
|
34
|
+
try {
|
|
35
|
+
const raw = await readFile(storePath(dir), "utf8");
|
|
36
|
+
return { ...defaultStore(), ...JSON.parse(raw) };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return defaultStore();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function saveStore(store, dir = commercialDataDir()) {
|
|
43
|
+
await writeJsonAtomic(storePath(dir), store);
|
|
44
|
+
}
|
|
45
|
+
export async function appendEntitlementEvent(event, dir = commercialDataDir()) {
|
|
46
|
+
await mkdir(dir, { recursive: true });
|
|
47
|
+
await appendFile(path.join(dir, "entitlement_events.jsonl"), JSON.stringify({ ...event, at: new Date().toISOString() }) + "\n", "utf8");
|
|
48
|
+
}
|
|
49
|
+
export function newId(prefix) {
|
|
50
|
+
return `${prefix}_${randomBytes(8).toString("hex")}`;
|
|
51
|
+
}
|
|
52
|
+
export async function upsertUserByEmail(email, dir = commercialDataDir()) {
|
|
53
|
+
const store = await loadStore(dir);
|
|
54
|
+
let user = store.users.find((u) => u.email.toLowerCase() === email.toLowerCase());
|
|
55
|
+
if (!user) {
|
|
56
|
+
user = {
|
|
57
|
+
id: newId("user"),
|
|
58
|
+
email,
|
|
59
|
+
createdAt: new Date().toISOString(),
|
|
60
|
+
stripeCustomerId: null,
|
|
61
|
+
};
|
|
62
|
+
store.users.push(user);
|
|
63
|
+
if (!store.subscriptions.some((s) => s.userId === user.id)) {
|
|
64
|
+
store.subscriptions.push({
|
|
65
|
+
id: newId("sub"),
|
|
66
|
+
userId: user.id,
|
|
67
|
+
status: "none",
|
|
68
|
+
plan: "free",
|
|
69
|
+
stripeSubscriptionId: null,
|
|
70
|
+
stripePriceId: null,
|
|
71
|
+
currentPeriodEnd: null,
|
|
72
|
+
cancelAtPeriodEnd: false,
|
|
73
|
+
updatedAt: new Date().toISOString(),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
await saveStore(store, dir);
|
|
77
|
+
}
|
|
78
|
+
return user;
|
|
79
|
+
}
|
|
80
|
+
export async function registerInstallation(userId, dir = commercialDataDir()) {
|
|
81
|
+
const store = await loadStore(dir);
|
|
82
|
+
const existing = store.installations.find((i) => i.userId === userId);
|
|
83
|
+
if (existing) {
|
|
84
|
+
existing.lastSeenAt = new Date().toISOString();
|
|
85
|
+
await saveStore(store, dir);
|
|
86
|
+
return existing;
|
|
87
|
+
}
|
|
88
|
+
const inst = {
|
|
89
|
+
id: newId("inst"),
|
|
90
|
+
userId,
|
|
91
|
+
hostname: os.hostname(),
|
|
92
|
+
platform: `${os.platform()}-${os.arch()}`,
|
|
93
|
+
createdAt: new Date().toISOString(),
|
|
94
|
+
lastSeenAt: new Date().toISOString(),
|
|
95
|
+
};
|
|
96
|
+
store.installations.push(inst);
|
|
97
|
+
await saveStore(store, dir);
|
|
98
|
+
return inst;
|
|
99
|
+
}
|
|
100
|
+
export async function getSubscriptionForUser(userId, dir = commercialDataDir()) {
|
|
101
|
+
const store = await loadStore(dir);
|
|
102
|
+
return store.subscriptions.find((s) => s.userId === userId) ?? null;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/commercial/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe TEST MODE integration.
|
|
3
|
+
* Secrets via env only — never commit.
|
|
4
|
+
*
|
|
5
|
+
* REWIND_STRIPE_SECRET_KEY=sk_test_…
|
|
6
|
+
* REWIND_STRIPE_WEBHOOK_SECRET=whsec_…
|
|
7
|
+
* REWIND_STRIPE_PRICE_ID=price_… (REWIND Personal £2.99 GBP/mo)
|
|
8
|
+
* REWIND_STRIPE_PUBLISHABLE_KEY=pk_test_…
|
|
9
|
+
*/
|
|
10
|
+
import { type SubscriptionStatus } from "../store.js";
|
|
11
|
+
export interface StripeConfig {
|
|
12
|
+
secretKey: string | null;
|
|
13
|
+
webhookSecret: string | null;
|
|
14
|
+
priceId: string | null;
|
|
15
|
+
publishableKey: string | null;
|
|
16
|
+
testMode: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Minimal Stripe surface used by REWIND (mockable in unit tests). */
|
|
19
|
+
export interface StripeClientLike {
|
|
20
|
+
customers: {
|
|
21
|
+
create: (params: {
|
|
22
|
+
email?: string;
|
|
23
|
+
metadata?: Record<string, string>;
|
|
24
|
+
}) => Promise<{
|
|
25
|
+
id: string;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
checkout: {
|
|
29
|
+
sessions: {
|
|
30
|
+
create: (params: Record<string, unknown>) => Promise<{
|
|
31
|
+
id: string;
|
|
32
|
+
url: string | null;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/** Test-only: inject a mock Stripe client (no network). */
|
|
38
|
+
export declare function setStripeClientForTests(client: StripeClientLike | null): void;
|
|
39
|
+
export declare function loadStripeConfig(): StripeConfig;
|
|
40
|
+
/** True when TEST secret + price are set — real Checkout, not simulated. */
|
|
41
|
+
export declare function isRealStripeTestConfigured(): boolean;
|
|
42
|
+
export declare function assertTestModeOrThrow(): void;
|
|
43
|
+
/** Verify Stripe-Signature header (idempotent-friendly). */
|
|
44
|
+
export declare function verifyStripeWebhookSignature(payload: string, header: string, secret: string, toleranceSec?: number): {
|
|
45
|
+
ok: boolean;
|
|
46
|
+
reason?: string;
|
|
47
|
+
};
|
|
48
|
+
export interface CheckoutSessionResult {
|
|
49
|
+
mode: "test-simulated" | "stripe";
|
|
50
|
+
url: string | null;
|
|
51
|
+
sessionId: string;
|
|
52
|
+
message: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create checkout. Without Stripe TEST credentials, simulates locally
|
|
56
|
+
* (activates Personal on confirm) so the product flow is provable offline.
|
|
57
|
+
* With sk_test_ + price_…, creates a real Stripe Checkout Session.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createCheckoutSession(input: {
|
|
60
|
+
userId: string;
|
|
61
|
+
email: string;
|
|
62
|
+
successUrl: string;
|
|
63
|
+
cancelUrl: string;
|
|
64
|
+
}): Promise<CheckoutSessionResult>;
|
|
65
|
+
export declare function confirmSimulatedCheckout(userId: string, sessionId: string): Promise<void>;
|
|
66
|
+
export interface ApplyWebhookResult {
|
|
67
|
+
applied: boolean;
|
|
68
|
+
duplicate: boolean;
|
|
69
|
+
userId: string | null;
|
|
70
|
+
plan: "free" | "personal" | null;
|
|
71
|
+
status: SubscriptionStatus | null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Legacy/test helper: apply a simplified webhook payload.
|
|
75
|
+
* Prefer applyStripeEvent for real Stripe Event objects.
|
|
76
|
+
*/
|
|
77
|
+
export declare function applyStripeWebhookEvent(eventId: string, type: string, data: {
|
|
78
|
+
customerId?: string;
|
|
79
|
+
subscriptionId?: string;
|
|
80
|
+
status?: string;
|
|
81
|
+
userId?: string;
|
|
82
|
+
cancelAtPeriodEnd?: boolean;
|
|
83
|
+
currentPeriodEnd?: number;
|
|
84
|
+
priceId?: string;
|
|
85
|
+
}): Promise<ApplyWebhookResult>;
|
|
86
|
+
/** Apply a real Stripe Event object (after signature verification). */
|
|
87
|
+
export declare function applyStripeEvent(event: {
|
|
88
|
+
id: string;
|
|
89
|
+
type: string;
|
|
90
|
+
data: {
|
|
91
|
+
object: Record<string, unknown>;
|
|
92
|
+
};
|
|
93
|
+
}): Promise<ApplyWebhookResult>;
|
|
94
|
+
/**
|
|
95
|
+
* HTTP webhook entry: verify raw body signature, then apply event.
|
|
96
|
+
* Never log secrets.
|
|
97
|
+
*/
|
|
98
|
+
export declare function handleStripeWebhookHttp(rawBody: string, signatureHeader: string | undefined): Promise<{
|
|
99
|
+
httpStatus: number;
|
|
100
|
+
body: Record<string, unknown>;
|
|
101
|
+
}>;
|
|
102
|
+
export declare function billingPortalMessage(): string;
|
|
103
|
+
/** Default local API port (loopback). */
|
|
104
|
+
export declare const LOCAL_API_DEFAULT_PORT = 7429;
|