@wopr-network/platform-core 1.0.0 → 1.0.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 (87) hide show
  1. package/coverage/coverage-summary.json +119 -0
  2. package/dist/admin/index.d.ts +1 -1
  3. package/dist/auth/better-auth.d.ts +45 -0
  4. package/dist/auth/better-auth.js +70 -47
  5. package/dist/auth/index.d.ts +12 -0
  6. package/dist/auth/index.js +7 -0
  7. package/dist/billing/drizzle-webhook-seen-repository.d.ts +1 -1
  8. package/dist/billing/index.d.ts +4 -4
  9. package/dist/billing/index.js +4 -4
  10. package/dist/billing/payram/webhook.test.js +1 -1
  11. package/dist/billing/stripe/index.d.ts +5 -5
  12. package/dist/billing/stripe/index.js +2 -2
  13. package/dist/billing/stripe/stripe-payment-processor.js +1 -1
  14. package/dist/credits/auto-topup-charge.d.ts +2 -2
  15. package/dist/credits/auto-topup-charge.test.js +1 -1
  16. package/dist/credits/auto-topup-schedule.d.ts +1 -1
  17. package/dist/credits/auto-topup-schedule.test.js +1 -1
  18. package/dist/credits/auto-topup-settings-repository.test.js +1 -1
  19. package/dist/credits/auto-topup-usage.d.ts +1 -1
  20. package/dist/credits/auto-topup-usage.test.js +1 -1
  21. package/dist/credits/index.d.ts +1 -1
  22. package/dist/credits/index.js +1 -1
  23. package/dist/db/schema/index.d.ts +1 -1
  24. package/dist/db/schema/index.js +1 -1
  25. package/dist/email/index.d.ts +1 -1
  26. package/dist/index.d.ts +4 -4
  27. package/dist/index.js +4 -3
  28. package/dist/metering/aggregator.test.js +1 -1
  29. package/dist/metering/emitter.test.js +1 -1
  30. package/dist/metering/load-test.bench.js +1 -1
  31. package/dist/metering/metering.test.js +1 -1
  32. package/dist/metering/reconciliation-cron.test.js +2 -2
  33. package/dist/metering/reconciliation-repository.test.js +1 -1
  34. package/dist/middleware/index.d.ts +3 -3
  35. package/dist/middleware/index.js +2 -2
  36. package/dist/security/credential-vault/index.d.ts +2 -2
  37. package/dist/security/index.d.ts +7 -7
  38. package/dist/security/index.js +7 -7
  39. package/dist/security/redirect-allowlist.js +10 -8
  40. package/dist/security/tenant-keys/index.d.ts +6 -6
  41. package/dist/security/tenant-keys/index.js +3 -3
  42. package/dist/tenancy/index.d.ts +3 -3
  43. package/dist/tenancy/org-service.d.ts +1 -1
  44. package/dist/tenancy/org-service.test.js +1 -1
  45. package/dist/trpc/index.d.ts +1 -1
  46. package/dist/trpc/index.js +1 -1
  47. package/dist/trpc/init.test.js +3 -5
  48. package/package.json +2 -1
  49. package/src/admin/index.ts +1 -1
  50. package/src/auth/better-auth.ts +129 -48
  51. package/src/auth/index.ts +31 -0
  52. package/src/billing/drizzle-webhook-seen-repository.ts +1 -1
  53. package/src/billing/index.ts +11 -13
  54. package/src/billing/payram/webhook.test.ts +1 -1
  55. package/src/billing/stripe/index.ts +17 -5
  56. package/src/billing/stripe/stripe-payment-processor.test.ts +2 -3
  57. package/src/billing/stripe/stripe-payment-processor.ts +1 -1
  58. package/src/credits/auto-topup-charge.test.ts +2 -2
  59. package/src/credits/auto-topup-charge.ts +2 -2
  60. package/src/credits/auto-topup-schedule.test.ts +1 -1
  61. package/src/credits/auto-topup-schedule.ts +1 -1
  62. package/src/credits/auto-topup-settings-repository.test.ts +1 -1
  63. package/src/credits/auto-topup-usage.test.ts +1 -1
  64. package/src/credits/auto-topup-usage.ts +1 -1
  65. package/src/credits/index.ts +1 -1
  66. package/src/db/schema/index.ts +1 -1
  67. package/src/email/index.ts +3 -3
  68. package/src/index.ts +13 -17
  69. package/src/metering/aggregator.test.ts +1 -1
  70. package/src/metering/emitter.test.ts +1 -1
  71. package/src/metering/load-test.bench.ts +1 -1
  72. package/src/metering/metering.test.ts +1 -1
  73. package/src/metering/reconciliation-cron.test.ts +2 -2
  74. package/src/metering/reconciliation-repository.test.ts +2 -2
  75. package/src/middleware/index.ts +5 -5
  76. package/src/middleware/rate-limit.test.ts +1 -1
  77. package/src/middleware/rate-limit.ts +1 -1
  78. package/src/security/credential-vault/index.ts +2 -2
  79. package/src/security/index.ts +43 -38
  80. package/src/security/redirect-allowlist.ts +11 -8
  81. package/src/security/tenant-keys/index.ts +10 -6
  82. package/src/tenancy/index.ts +3 -3
  83. package/src/tenancy/org-service.test.ts +1 -1
  84. package/src/tenancy/org-service.ts +1 -1
  85. package/src/trpc/index.ts +5 -5
  86. package/src/trpc/init.test.ts +8 -10
  87. package/vitest.config.ts +4 -0
@@ -1,11 +1,11 @@
1
1
  import crypto from "node:crypto";
2
2
  import type { PGlite } from "@electric-sql/pglite";
3
3
  import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { Credit } from "../credits/credit.js";
5
+ import { CreditLedger } from "../credits/credit-ledger.js";
4
6
  import type { PlatformDb } from "../db/index.js";
5
7
  import { usageSummaries } from "../db/schema/meter-events.js";
6
8
  import { createTestDb, truncateAllTables } from "../test/db.js";
7
- import { Credit } from "../credits/credit.js";
8
- import { CreditLedger } from "../credits/credit-ledger.js";
9
9
  import { runReconciliation } from "./reconciliation-cron.js";
10
10
  import { DrizzleAdapterUsageRepository, DrizzleUsageSummaryRepository } from "./reconciliation-repository.js";
11
11
 
@@ -1,10 +1,10 @@
1
1
  import crypto from "node:crypto";
2
2
  import type { PGlite } from "@electric-sql/pglite";
3
3
  import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
4
- import type { PlatformDb } from "../db/index.js";
5
- import { createTestDb, seedUsageSummary, truncateAllTables } from "../test/db.js";
6
4
  import { Credit } from "../credits/credit.js";
7
5
  import { CreditLedger } from "../credits/credit-ledger.js";
6
+ import type { PlatformDb } from "../db/index.js";
7
+ import { createTestDb, seedUsageSummary, truncateAllTables } from "../test/db.js";
8
8
  import { DrizzleAdapterUsageRepository, DrizzleUsageSummaryRepository } from "./reconciliation-repository.js";
9
9
 
10
10
  let pool: PGlite;
@@ -1,12 +1,12 @@
1
- export type { IRateLimitRepository, RateLimitEntry } from "./rate-limit-repository.js";
1
+ export { type CsrfOptions, csrfProtection, validateCsrfOrigin } from "./csrf.js";
2
2
  export { DrizzleRateLimitRepository } from "./drizzle-rate-limit-repository.js";
3
+ export { getClientIpFromContext } from "./get-client-ip.js";
3
4
  export {
4
- rateLimit,
5
- rateLimitByRoute,
6
5
  getClientIp,
7
6
  parseTrustedProxies,
8
7
  type RateLimitConfig,
9
8
  type RateLimitRule,
9
+ rateLimit,
10
+ rateLimitByRoute,
10
11
  } from "./rate-limit.js";
11
- export { getClientIpFromContext } from "./get-client-ip.js";
12
- export { csrfProtection, validateCsrfOrigin, type CsrfOptions } from "./csrf.js";
12
+ export type { IRateLimitRepository, RateLimitEntry } from "./rate-limit-repository.js";
@@ -10,7 +10,6 @@ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi }
10
10
  import type { PlatformDb } from "../db/index.js";
11
11
  import { createTestDb, truncateAllTables } from "../test/db.js";
12
12
  import { DrizzleRateLimitRepository } from "./drizzle-rate-limit-repository.js";
13
- import type { IRateLimitRepository } from "./rate-limit-repository.js";
14
13
  import {
15
14
  getClientIp,
16
15
  parseTrustedProxies,
@@ -19,6 +18,7 @@ import {
19
18
  rateLimit,
20
19
  rateLimitByRoute,
21
20
  } from "./rate-limit.js";
21
+ import type { IRateLimitRepository } from "./rate-limit-repository.js";
22
22
 
23
23
  // ---------------------------------------------------------------------------
24
24
  // Helpers
@@ -10,8 +10,8 @@
10
10
  */
11
11
 
12
12
  import type { Context, MiddlewareHandler, Next } from "hono";
13
- import type { IRateLimitRepository } from "./rate-limit-repository.js";
14
13
  import { getClientIpFromContext } from "./get-client-ip.js";
14
+ import type { IRateLimitRepository } from "./rate-limit-repository.js";
15
15
 
16
16
  export { getClientIp, parseTrustedProxies } from "./get-client-ip.js";
17
17
 
@@ -1,12 +1,12 @@
1
- export type { SecretAuditEvent, ISecretAuditRepository } from "./audit-repository.js";
1
+ export type { ISecretAuditRepository, SecretAuditEvent } from "./audit-repository.js";
2
2
  export { DrizzleSecretAuditRepository } from "./audit-repository.js";
3
3
  export type {
4
4
  CredentialRow,
5
5
  CredentialSummaryRow,
6
- InsertCredentialRow,
7
6
  ICredentialMigrationAccess,
8
7
  ICredentialRepository,
9
8
  IMigrationTenantKeyAccess,
9
+ InsertCredentialRow,
10
10
  } from "./credential-repository.js";
11
11
  export { DrizzleCredentialRepository, DrizzleMigrationTenantKeyAccess } from "./credential-repository.js";
12
12
  export type { RotationResult } from "./key-rotation.js";
@@ -1,59 +1,64 @@
1
- export type { EncryptedPayload, Provider, ValidateKeyRequest, ValidateKeyResponse, WriteSecretsRequest, ProviderEndpoint } from "./types.js";
2
- export { providerSchema, validateKeyRequestSchema, writeSecretsRequestSchema } from "./types.js";
3
- export { deriveInstanceKey, generateInstanceKey, encrypt, decrypt } from "./encryption.js";
4
- export { validateNodeHost } from "./host-validation.js";
5
- export { assertSafeRedirectUrl } from "./redirect-allowlist.js";
6
- export type { KeyLeakMatch } from "./key-audit.js";
7
- export { scanForKeyLeaks } from "./key-audit.js";
8
- export { writeEncryptedSeed, forwardSecretsToInstance } from "./key-injection.js";
9
- export { PROVIDER_ENDPOINTS, validateProviderKey } from "./key-validation.js";
10
-
11
1
  // Credential vault
12
2
  export {
13
- type SecretAuditEvent,
14
- type ISecretAuditRepository,
15
- DrizzleSecretAuditRepository,
3
+ type AuthType,
4
+ auditCredentialEncryption,
5
+ type CreateCredentialInput,
16
6
  type CredentialRow,
7
+ type CredentialSummary,
17
8
  type CredentialSummaryRow,
18
- type InsertCredentialRow,
9
+ CredentialVaultStore,
10
+ type DecryptedCredential,
11
+ DrizzleCredentialRepository,
12
+ DrizzleMigrationTenantKeyAccess,
13
+ DrizzleSecretAuditRepository,
14
+ getVaultEncryptionKey,
19
15
  type ICredentialMigrationAccess,
20
16
  type ICredentialRepository,
17
+ type ICredentialVaultStore,
21
18
  type IMigrationTenantKeyAccess,
22
- DrizzleCredentialRepository,
23
- DrizzleMigrationTenantKeyAccess,
24
- type RotationResult,
25
- reEncryptAllCredentials,
19
+ type InsertCredentialRow,
20
+ type ISecretAuditRepository,
26
21
  type MigrationResult,
27
22
  migratePlaintextCredentials,
28
23
  type PlaintextFinding,
29
- auditCredentialEncryption,
30
- type AuthType,
31
- type CreateCredentialInput,
32
- type CredentialSummary,
33
- type DecryptedCredential,
34
- type ICredentialVaultStore,
35
24
  type RotateCredentialInput,
36
- CredentialVaultStore,
37
- getVaultEncryptionKey,
25
+ type RotationResult,
26
+ reEncryptAllCredentials,
27
+ type SecretAuditEvent,
38
28
  } from "./credential-vault/index.js";
39
-
29
+ export { decrypt, deriveInstanceKey, encrypt, generateInstanceKey } from "./encryption.js";
30
+ export { validateNodeHost } from "./host-validation.js";
31
+ export type { KeyLeakMatch } from "./key-audit.js";
32
+ export { scanForKeyLeaks } from "./key-audit.js";
33
+ export { forwardSecretsToInstance, writeEncryptedSeed } from "./key-injection.js";
34
+ export { PROVIDER_ENDPOINTS, validateProviderKey } from "./key-validation.js";
35
+ export { assertSafeRedirectUrl } from "./redirect-allowlist.js";
40
36
  // Tenant keys
41
37
  export {
42
- type IKeyResolutionRepository,
43
- DrizzleKeyResolutionRepository,
44
- type ResolvedKey,
45
- resolveApiKey,
38
+ ALL_CAPABILITIES,
46
39
  buildPooledKeysMap,
47
- type TenantApiKey,
48
- type ITenantKeyRepository,
49
- TenantKeyRepository,
50
40
  type CapabilityName,
51
- type TenantCapabilitySetting,
52
- type ICapabilitySettingsRepository,
53
- ALL_CAPABILITIES,
54
41
  CapabilitySettingsStore,
42
+ DrizzleKeyResolutionRepository,
43
+ DrizzleOrgMembershipRepository,
44
+ type ICapabilitySettingsRepository,
45
+ type IKeyResolutionRepository,
55
46
  type IOrgMembershipRepository,
47
+ type ITenantKeyRepository,
56
48
  type OrgResolvedKey,
57
- DrizzleOrgMembershipRepository,
49
+ type ResolvedKey,
50
+ resolveApiKey,
58
51
  resolveApiKeyWithOrgFallback,
52
+ type TenantApiKey,
53
+ type TenantCapabilitySetting,
54
+ TenantKeyRepository,
59
55
  } from "./tenant-keys/index.js";
56
+ export type {
57
+ EncryptedPayload,
58
+ Provider,
59
+ ProviderEndpoint,
60
+ ValidateKeyRequest,
61
+ ValidateKeyResponse,
62
+ WriteSecretsRequest,
63
+ } from "./types.js";
64
+ export { providerSchema, validateKeyRequestSchema, writeSecretsRequestSchema } from "./types.js";
@@ -1,10 +1,13 @@
1
- const ALLOWED_REDIRECT_ORIGINS: string[] = [
2
- "https://app.wopr.bot",
3
- "https://wopr.network",
4
- ...(process.env.NODE_ENV !== "production" ? ["http://localhost:3000", "http://localhost:3001"] : []),
5
- ...(process.env.PLATFORM_UI_URL ? [process.env.PLATFORM_UI_URL] : []),
6
- ...(process.env.NODE_ENV !== "production" ? ["https://example.com"] : []),
7
- ];
1
+ const STATIC_ORIGINS: string[] = ["https://app.wopr.bot", "https://wopr.network"];
2
+
3
+ function getAllowedOrigins(): string[] {
4
+ return [
5
+ ...STATIC_ORIGINS,
6
+ ...(process.env.NODE_ENV !== "production" ? ["http://localhost:3000", "http://localhost:3001"] : []),
7
+ ...(process.env.PLATFORM_UI_URL ? [process.env.PLATFORM_UI_URL] : []),
8
+ ...(process.env.NODE_ENV !== "production" ? ["https://example.com"] : []),
9
+ ];
10
+ }
8
11
 
9
12
  /**
10
13
  * Throws if `url` is not rooted at one of the allowed origins.
@@ -22,7 +25,7 @@ export function assertSafeRedirectUrl(url: string): void {
22
25
  throw new Error("Invalid redirect URL");
23
26
  }
24
27
  const origin = parsed.origin;
25
- const allowed = ALLOWED_REDIRECT_ORIGINS.some((o) => {
28
+ const allowed = getAllowedOrigins().some((o) => {
26
29
  try {
27
30
  return origin === new URL(o).origin;
28
31
  } catch {
@@ -1,10 +1,14 @@
1
+ export type {
2
+ CapabilityName,
3
+ ICapabilitySettingsRepository,
4
+ TenantCapabilitySetting,
5
+ } from "./capability-settings-store.js";
6
+ export { ALL_CAPABILITIES, CapabilitySettingsStore } from "./capability-settings-store.js";
7
+ export type { ResolvedKey } from "./key-resolution.js";
8
+ export { buildPooledKeysMap, resolveApiKey } from "./key-resolution.js";
1
9
  export type { IKeyResolutionRepository } from "./key-resolution-repository.js";
2
10
  export { DrizzleKeyResolutionRepository } from "./key-resolution-repository.js";
3
- export type { ResolvedKey } from "./key-resolution.js";
4
- export { resolveApiKey, buildPooledKeysMap } from "./key-resolution.js";
5
- export type { TenantApiKey, ITenantKeyRepository } from "./tenant-key-repository.js";
6
- export { TenantKeyRepository } from "./tenant-key-repository.js";
7
- export type { CapabilityName, TenantCapabilitySetting, ICapabilitySettingsRepository } from "./capability-settings-store.js";
8
- export { ALL_CAPABILITIES, CapabilitySettingsStore } from "./capability-settings-store.js";
9
11
  export type { IOrgMembershipRepository, OrgResolvedKey } from "./org-key-resolution.js";
10
12
  export { DrizzleOrgMembershipRepository, resolveApiKeyWithOrgFallback } from "./org-key-resolution.js";
13
+ export type { ITenantKeyRepository, TenantApiKey } from "./tenant-key-repository.js";
14
+ export { TenantKeyRepository } from "./tenant-key-repository.js";
@@ -1,6 +1,6 @@
1
- export type { Tenant, IOrgRepository } from "./drizzle-org-repository.js";
1
+ export type { IOrgRepository, Tenant } from "./drizzle-org-repository.js";
2
2
  export { DrizzleOrgRepository } from "./drizzle-org-repository.js";
3
- export type { OrgMemberRow, OrgInviteRow, IOrgMemberRepository } from "./org-member-repository.js";
3
+ export type { IOrgMemberRepository, OrgInviteRow, OrgMemberRow } from "./org-member-repository.js";
4
4
  export { DrizzleOrgMemberRepository } from "./org-member-repository.js";
5
- export type { OrgWithMembers, OrgMemberWithUser, OrgInvitePublic, OrgServiceOptions } from "./org-service.js";
5
+ export type { OrgInvitePublic, OrgMemberWithUser, OrgServiceOptions, OrgWithMembers } from "./org-service.js";
6
6
  export { OrgService } from "./org-service.js";
@@ -2,9 +2,9 @@ import type { PGlite } from "@electric-sql/pglite";
2
2
  import { TRPCError } from "@trpc/server";
3
3
  import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
4
4
  import type { PlatformDb } from "../db/index.js";
5
- import { DrizzleOrgMemberRepository } from "./org-member-repository.js";
6
5
  import { createTestDb, truncateAllTables } from "../test/db.js";
7
6
  import { DrizzleOrgRepository } from "./drizzle-org-repository.js";
7
+ import { DrizzleOrgMemberRepository } from "./org-member-repository.js";
8
8
  import { OrgService } from "./org-service.js";
9
9
 
10
10
  async function setup(db: PlatformDb) {
@@ -10,8 +10,8 @@ import { eq } from "drizzle-orm";
10
10
  import { logger } from "../config/logger.js";
11
11
  import type { PlatformDb } from "../db/index.js";
12
12
  import { organizationInvites, organizationMembers, tenants } from "../db/schema/index.js";
13
- import type { IOrgMemberRepository, OrgInviteRow } from "./org-member-repository.js";
14
13
  import type { IOrgRepository, Tenant } from "./drizzle-org-repository.js";
14
+ import type { IOrgMemberRepository, OrgInviteRow } from "./org-member-repository.js";
15
15
 
16
16
  // ---------------------------------------------------------------------------
17
17
  // Types
package/src/trpc/index.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export {
2
- router,
3
- createCallerFactory,
4
- publicProcedure,
5
- protectedProcedure,
6
2
  adminProcedure,
7
- tenantProcedure,
3
+ createCallerFactory,
8
4
  orgMemberProcedure,
5
+ protectedProcedure,
6
+ publicProcedure,
7
+ router,
9
8
  setTrpcOrgMemberRepo,
10
9
  type TRPCContext,
10
+ tenantProcedure,
11
11
  } from "./init.js";
@@ -1,14 +1,14 @@
1
- import { describe, expect, it, vi, beforeEach } from "vitest";
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
  import type { IOrgMemberRepository } from "../tenancy/org-member-repository.js";
3
3
  import {
4
- router,
5
- createCallerFactory,
6
- publicProcedure,
7
- protectedProcedure,
8
4
  adminProcedure,
9
- tenantProcedure,
5
+ createCallerFactory,
10
6
  orgMemberProcedure,
7
+ protectedProcedure,
8
+ publicProcedure,
9
+ router,
11
10
  setTrpcOrgMemberRepo,
11
+ tenantProcedure,
12
12
  } from "./init.js";
13
13
 
14
14
  // ---------------------------------------------------------------------------
@@ -41,9 +41,7 @@ const appRouter = router({
41
41
  protectedHello: protectedProcedure.query(() => "protected-ok"),
42
42
  adminHello: adminProcedure.query(() => "admin-ok"),
43
43
  tenantHello: tenantProcedure.query(() => "tenant-ok"),
44
- orgAction: orgMemberProcedure
45
- .input((v: unknown) => v as { orgId: string })
46
- .mutation(() => "org-ok"),
44
+ orgAction: orgMemberProcedure.input((v: unknown) => v as { orgId: string }).mutation(() => "org-ok"),
47
45
  });
48
46
 
49
47
  const createCaller = createCallerFactory(appRouter);
@@ -172,7 +170,7 @@ describe("tRPC procedure builders", () => {
172
170
 
173
171
  it("rejects when orgId is missing from input", async () => {
174
172
  const caller = createCaller({ user: { id: "u1", roles: ["user"] }, tenantId: undefined });
175
- await expect(caller.orgAction({} as any)).rejects.toThrow("orgId is required");
173
+ await expect(caller.orgAction({} as unknown as { orgId: string })).rejects.toThrow("orgId is required");
176
174
  });
177
175
 
178
176
  it("rejects non-members", async () => {
package/vitest.config.ts CHANGED
@@ -4,5 +4,9 @@ export default defineConfig({
4
4
  test: {
5
5
  testTimeout: 30000,
6
6
  include: ["src/**/*.test.ts"],
7
+ coverage: {
8
+ provider: "v8",
9
+ reporter: ["text", "json-summary", "json"],
10
+ },
7
11
  },
8
12
  });