@almadar/integrations 2.24.0 → 2.25.0

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.
@@ -0,0 +1,59 @@
1
+ import { I as IntegrationConfig, B as BaseIntegration, e as IntegrationParams, f as IntegrationResult } from './BaseIntegration-MA-b4fh8.js';
2
+
3
+ /**
4
+ * Optional per-call context for principal-scoped resolution (W4). The
5
+ * default — absent — means the tenant/app-wide credential set; a `principal`
6
+ * selects a per-principal configuration when one was registered. Additive:
7
+ * every existing call site is untouched.
8
+ */
9
+ interface IntegrationCallContext {
10
+ principal?: string;
11
+ }
12
+ /**
13
+ * Factory for creating and managing integration instances
14
+ */
15
+ declare class IntegrationFactory {
16
+ private instances;
17
+ private configs;
18
+ /**
19
+ * Configure an integration (doesn't instantiate yet). A `principal` scopes
20
+ * the config to that principal; the app-wide config (no principal) is the
21
+ * fallback for every principal.
22
+ */
23
+ configure(name: string, config: Omit<IntegrationConfig, 'name'>, principal?: string): void;
24
+ /**
25
+ * Get or create an integration instance. Principal-scoped lookups fall
26
+ * back to the app-wide config when no per-principal config exists.
27
+ */
28
+ get(name: string, principal?: string): BaseIntegration;
29
+ /**
30
+ * Execute an action on an integration
31
+ */
32
+ execute(integration: string, action: string, params: IntegrationParams, context?: IntegrationCallContext): Promise<IntegrationResult>;
33
+ /**
34
+ * Check if integration is configured
35
+ */
36
+ isConfigured(name: string, principal?: string): boolean;
37
+ /**
38
+ * Register an integration instance directly (used by mock infrastructure)
39
+ */
40
+ registerInstance(name: string, instance: BaseIntegration, principal?: string): void;
41
+ /**
42
+ * Drop the cached instance(s) for a name so the next `get` rebuilds from
43
+ * the current config — how a credential change goes live without restart.
44
+ * Configs are kept; without a name, every instance is dropped.
45
+ */
46
+ invalidate(name?: string): void;
47
+ /**
48
+ * Clear all instances (useful for testing)
49
+ */
50
+ clear(): void;
51
+ /**
52
+ * Clear all instances and configs
53
+ */
54
+ reset(): void;
55
+ }
56
+ declare function getIntegrationFactory(): IntegrationFactory;
57
+ declare function resetIntegrationFactory(): void;
58
+
59
+ export { type IntegrationCallContext as I, IntegrationFactory as a, getIntegrationFactory as g, resetIntegrationFactory as r };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import { c as IntegrationLogger, b as IntegrationErrorCode, I as IntegrationConfig, B as BaseIntegration, e as IntegrationParams, f as IntegrationResult } from './BaseIntegration-MA-b4fh8.js';
2
2
  export { a as IntegrationError, d as IntegrationParamValue, V as ValidationError, g as ValidationResult, v as validateParams } from './BaseIntegration-MA-b4fh8.js';
3
- export { A as ArxivActions, C as CLIActions, D as DatabaseActions, a as DatabaseDriver, b as DatabaseQueryParamValue, c as DatabaseQueryParams, d as DatabaseQueryResult, e as DatabaseRow, f as DeepAgentActions, g as DockerActions, E as EmailActions, G as GitHubActions, I as IconifyActions, h as IntegrationActionName, i as IntegrationContracts, j as IntegrationName, L as LLMIntegrationActions, M as MLActions, O as OAuthActions, k as OtelActions, Q as QueueActions, R as RedisActions, S as StorageActions, l as StripeActions, T as TwilioActions, W as WebhookActions, m as WikimediaActions, Y as YouTubeActions } from './contracts-Dv9PM_Cz.js';
3
+ import { e as CredentialStore } from './store-CW1v7Apc.js';
4
+ export { A as ArxivActions, C as CLIActions, a as CREDENTIAL_ENTITY_TYPE, b as CREDENTIAL_MASTER_KEY_ENV, c as CredentialEntry, d as CredentialPersistence, D as DatabaseActions, f as DatabaseDriver, g as DatabaseQueryParamValue, h as DatabaseQueryParams, i as DatabaseQueryResult, j as DatabaseRow, k as DeepAgentActions, l as DockerActions, E as EmailActions, G as GitHubActions, I as IconifyActions, m as IntegrationActionName, n as IntegrationContracts, o as IntegrationName, L as LLMIntegrationActions, M as MLActions, O as OAuthActions, p as OtelActions, Q as QueueActions, R as RedisActions, S as StorageActions, q as StripeActions, T as TwilioActions, W as WebhookActions, r as WikimediaActions, Y as YouTubeActions } from './store-CW1v7Apc.js';
4
5
  import { LogMeta } from '@almadar/core';
5
- export { I as IntegrationFactory, g as getIntegrationFactory, r as resetIntegrationFactory } from './factory-DTdVeyAi.js';
6
+ import { a as IntegrationFactory } from './factory-BPVhvv5q.js';
7
+ export { I as IntegrationCallContext, g as getIntegrationFactory, r as resetIntegrationFactory } from './factory-BPVhvv5q.js';
6
8
  export { GitHubIntegration } from './integrations/github/index.js';
7
9
 
8
10
  /**
@@ -61,6 +63,31 @@ declare function isKnownIntegration(name: string): boolean;
61
63
  */
62
64
  declare function getRegisteredIntegrations(): string[];
63
65
 
66
+ /**
67
+ * The factory the host's `RuntimeIntegrationManager` configures — installed
68
+ * by its constructor so the `credentials.test` probe executes through the
69
+ * SAME factory (and therefore the same configs) as every other call-service.
70
+ */
71
+ declare function installActiveFactory(factory: IntegrationFactory): void;
72
+ declare function getActiveFactory(): IntegrationFactory | null;
73
+ /**
74
+ * Install the host's credential store as the process-wide resolution source.
75
+ * Called once at boot (playground / generated server) after the store is
76
+ * constructed over the host's persistence adapter.
77
+ */
78
+ declare function installCredentialStore(store: CredentialStore): void;
79
+ /** The installed store, for the credentials admin service. */
80
+ declare function getInstalledCredentialStore(): CredentialStore | null;
81
+ /** Testing/reset hook. */
82
+ declare function uninstallCredentialStore(): void;
83
+ /**
84
+ * The one credential-reference resolver: store → env → undefined.
85
+ * `ref` is an env-var name — the same name `serviceCredentials` declares and
86
+ * `connectionRef` params carry. Every place that used to read
87
+ * `process.env[ref]` for a credential routes through here.
88
+ */
89
+ declare function resolveCredentialRef(ref: string, env?: Record<string, string | undefined>): string | undefined;
90
+
64
91
  /**
65
92
  * Canonical Almadar shapes for the Stripe integration.
66
93
  *
@@ -352,6 +379,171 @@ declare class WebhookIntegration extends BaseIntegration {
352
379
  private send;
353
380
  }
354
381
 
382
+ /**
383
+ * Web Push integration — VAPID-signed push notifications to browser
384
+ * PushSubscription endpoints. VAPID details are passed per call (never via the
385
+ * web-push module singleton) so concurrent configs cannot contaminate each other.
386
+ */
387
+ declare class PushIntegration extends BaseIntegration {
388
+ private vapidPublicKey;
389
+ private vapidPrivateKey;
390
+ private vapidSubject;
391
+ constructor(config: IntegrationConfig);
392
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
393
+ private send;
394
+ }
395
+
396
+ /**
397
+ * Verify + parse Google Calendar push notifications (watch channels) into the
398
+ * canonical Almadar hook event. Google sends NO body — everything rides the
399
+ * `X-Goog-*` headers — and offers no HMAC; the only verifiable secret is the
400
+ * channel token we supplied at `calendar.watch` time, so pass `expectedToken`
401
+ * whenever the watch was registered with one.
402
+ *
403
+ * The googleapis SDK never appears here or in any route — this module is the
404
+ * whole provider surface, mirroring `stripe/webhooks.ts`.
405
+ */
406
+ type CalendarHookEvent = {
407
+ type: 'calendar.changed';
408
+ channelId: string;
409
+ resourceId: string;
410
+ /** `sync` (channel handshake), `exists`, or `not_exists`. */
411
+ resourceState: string;
412
+ messageNumber: number;
413
+ } | {
414
+ error: 'missing-headers';
415
+ } | {
416
+ error: 'bad-token';
417
+ };
418
+ declare function parseCalendarPushNotification(headers: Record<string, string | undefined>, expectedToken?: string): CalendarHookEvent;
419
+ /**
420
+ * Hook-provider adapter for the shared `/api/hooks/:provider` ingress: maps a
421
+ * Google Calendar push notification to the bus event `CAL_REMOTE_CHANGED`
422
+ * consumed by `std-calendar-sync`. The `sync` handshake message acknowledges
423
+ * without dispatching (it announces the channel, not a data change).
424
+ */
425
+ declare function googleCalendarHookProvider(expectedToken?: string): (input: {
426
+ headers: Record<string, string | undefined>;
427
+ rawBody: string;
428
+ }) => {
429
+ event: string;
430
+ payload: {
431
+ channelId: string;
432
+ resourceId: string;
433
+ resourceState: string;
434
+ };
435
+ } | {
436
+ error: string;
437
+ } | {
438
+ ack: true;
439
+ };
440
+
441
+ /**
442
+ * Google Calendar integration — service account auth, optionally acting as a
443
+ * Workspace user via domain-wide delegation (GOOGLE_CALENDAR_SUBJECT). All
444
+ * event times are ISO strings on the wire; a 10-char value (YYYY-MM-DD) maps
445
+ * to an all-day `date`, anything longer to `dateTime`.
446
+ */
447
+ declare class CalendarIntegration extends BaseIntegration {
448
+ private client;
449
+ private defaultCalendarId;
450
+ constructor(config: IntegrationConfig);
451
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
452
+ private calendarId;
453
+ private toEventTime;
454
+ private fromEventTime;
455
+ private listEvents;
456
+ private resolveEnd;
457
+ private createEvent;
458
+ private updateEvent;
459
+ private deleteEvent;
460
+ private freeBusy;
461
+ private watch;
462
+ private stopWatch;
463
+ }
464
+
465
+ /**
466
+ * Google Drive integration — service account auth, optionally acting as a
467
+ * Workspace user via domain-wide delegation (GOOGLE_DRIVE_SUBJECT). File
468
+ * content crosses this boundary as base64 (data URL accepted on upload).
469
+ */
470
+ declare class DriveIntegration extends BaseIntegration {
471
+ private client;
472
+ constructor(config: IntegrationConfig);
473
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
474
+ private listFiles;
475
+ private getFile;
476
+ private uploadFile;
477
+ private createFolder;
478
+ private shareFile;
479
+ }
480
+
481
+ /**
482
+ * Meta Ads integration — Graph API Marketing Insights, READ-ONLY (spend and
483
+ * campaign listings for profitability reporting). No SDK: plain fetch with
484
+ * the webhook integration's 5xx-retries / 4xx-returns split.
485
+ */
486
+ declare class MetaAdsIntegration extends BaseIntegration {
487
+ private accessToken;
488
+ private defaultAccountId;
489
+ constructor(config: IntegrationConfig);
490
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
491
+ private accountId;
492
+ private graphGet;
493
+ private getSpend;
494
+ private listCampaigns;
495
+ }
496
+
497
+ /**
498
+ * Accounting export integration — the generic half of "export to accounting
499
+ * software": shapes invoice / journal rows into import-ready CSV without
500
+ * committing to a vendor. A `provider` field is reserved on the config for
501
+ * direct DATEV/Xero/QuickBooks connectors later; the CSV column sets follow
502
+ * the common import templates those systems accept.
503
+ */
504
+ declare class AccountingIntegration extends BaseIntegration {
505
+ constructor(config: IntegrationConfig);
506
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
507
+ private exportRows;
508
+ }
509
+
510
+ /**
511
+ * Banking integration — GoCardless Bank Account Data (read-only requisition →
512
+ * accounts → transactions flow feeding reconciliation). Access tokens are
513
+ * minted per instance from the secret pair and refreshed on expiry.
514
+ */
515
+ declare class BankingIntegration extends BaseIntegration {
516
+ private secretId;
517
+ private secretKey;
518
+ private accessToken;
519
+ private accessTokenExpiresAt;
520
+ constructor(config: IntegrationConfig);
521
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
522
+ private token;
523
+ private gcRequest;
524
+ private createRequisition;
525
+ private listAccounts;
526
+ private listTransactions;
527
+ }
528
+
529
+ /**
530
+ * E-signature integration — DocuSign eSignature REST first, deliberately
531
+ * provider-pluggable: the action surface (sendEnvelope / getEnvelopeStatus /
532
+ * downloadDocument) is vendor-neutral and every DocuSign shape stays inside
533
+ * this module. `DOCUSIGN_BASE_URL` carries the account-scoped REST base;
534
+ * `DOCUSIGN_ACCESS_TOKEN` the OAuth token (JWT-grant rotation is the
535
+ * deployment's concern — the token is read per call so a rotated env value
536
+ * takes effect without restart).
537
+ */
538
+ declare class EsignIntegration extends BaseIntegration {
539
+ constructor(config: IntegrationConfig);
540
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
541
+ private dsRequest;
542
+ private sendEnvelope;
543
+ private getEnvelopeStatus;
544
+ private downloadDocument;
545
+ }
546
+
355
547
  /**
356
548
  * LLM integration using @almadar/llm
357
549
  *
@@ -503,23 +695,47 @@ declare class OtelIntegration extends BaseIntegration {
503
695
  }
504
696
 
505
697
  /**
506
- * OAuth2/OIDC integration with in-memory mock backend.
698
+ * OAuth2/OIDC integration.
507
699
  *
508
- * This is a development/mock implementation. No actual OAuth library is used.
509
- * State tokens, access tokens, and refresh tokens are generated in-memory and
510
- * tracked via Maps. Useful for testing OAuth flows without external providers.
700
+ * Two backends behind one contract:
701
+ * - **OIDC (production)** `openid-client` against a discovered issuer
702
+ * (default Google; override via `OIDC_ISSUER_URL`), authorization-code +
703
+ * PKCE, real token exchange / refresh / revocation / userinfo. Selected
704
+ * whenever `OAUTH_CLIENT_ID` + `OAUTH_CLIENT_SECRET` are configured and
705
+ * `OAUTH_MODE` is not `mock`.
706
+ * - **Mock (dev/tests)** — the original in-memory backend, kept verbatim
707
+ * behind `OAUTH_MODE=mock` (or absent client credentials) so existing
708
+ * tests and offline dev flows are untouched.
709
+ *
710
+ * Pending-authorization state (PKCE verifier, redirect URI) is held
711
+ * in-process keyed by `state` — multi-instance deployments need sticky
712
+ * routing between authorize and token (ledger note).
511
713
  */
512
714
  declare class OAuthIntegration extends BaseIntegration {
513
- /** Maps state token -> provider for pending authorization flows */
715
+ /** Maps state token -> provider for pending MOCK authorization flows */
514
716
  private states;
515
- /** Maps access token -> token set */
717
+ /** Maps access token -> token set (mock backend) */
516
718
  private tokens;
517
- /** Maps refresh token -> access token for refresh lookups */
719
+ /** Maps refresh token -> access token for refresh lookups (mock backend) */
518
720
  private refreshIndex;
519
721
  /** Maps access token -> mock user session */
520
722
  private sessions;
723
+ /** Maps state -> pending OIDC authorization (real backend) */
724
+ private pending;
725
+ /** Maps access token -> ID-token subject, for userinfo subject checks */
726
+ private subjects;
727
+ /** Discovered issuer configurations, keyed by issuer URL */
728
+ private discovered;
729
+ private readonly real;
521
730
  constructor(config: IntegrationConfig);
522
731
  execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
732
+ private issuerFor;
733
+ private configurationFor;
734
+ private oidcAuthorize;
735
+ private oidcToken;
736
+ private oidcRefresh;
737
+ private oidcRevoke;
738
+ private oidcUserinfo;
523
739
  /** Generate a random hex token of the given byte length. */
524
740
  private generateToken;
525
741
  /** Generate a mock user profile from a provider and access token. */
@@ -532,26 +748,57 @@ declare class OAuthIntegration extends BaseIntegration {
532
748
  }
533
749
 
534
750
  /**
535
- * Storage integration with in-memory backend for development/testing.
751
+ * The hosted credential store's service surface (W4 Tier C) — what the
752
+ * Owner-gated Integrations settings page calls through the NORMAL
753
+ * call-service path (server-side only; organisms own the access policy,
754
+ * per the I-16 std-atom ACL constraint).
755
+ *
756
+ * Security contract: `list` returns masked entries only (last-4, never
757
+ * plaintext); `set` accepts only env vars DECLARED in `serviceCredentials`
758
+ * for the named service (plus well-formed connection refs for `database`),
759
+ * so the page can never become an arbitrary env-injection surface; values
760
+ * are never logged.
761
+ */
762
+ declare class CredentialsIntegration extends BaseIntegration {
763
+ constructor(config: IntegrationConfig);
764
+ execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
765
+ private declaredFor;
766
+ private assertSettable;
767
+ private list;
768
+ private set;
769
+ private remove;
770
+ private test;
771
+ }
772
+
773
+ /**
774
+ * Object storage integration — real S3-compatible backend (AWS S3, R2, MinIO,
775
+ * …) when `STORAGE_ACCESS_KEY_ID`/`STORAGE_SECRET_ACCESS_KEY` are configured,
776
+ * in-memory simulation otherwise. Production REFUSES the in-memory fallback:
777
+ * a missing credential must fail loudly, never simulate success (D-3).
536
778
  *
537
- * Provides S3-compatible object storage operations (upload, download, list,
538
- * delete, getSignedUrl) backed by an in-memory Map. No cloud SDK dependencies
539
- * are required.
779
+ * `upload` admits two shapes: the canonical `{ key, content }` pair and the
780
+ * file-form `{ file: { name, size, type, content }, acl?, maxSize? }` that
781
+ * lolo authors wire from UploadDropZone. The result carries `id`/`url`
782
+ * alongside `key` — the fields the .lolo consumers read.
540
783
  */
541
784
  declare class StorageIntegration extends BaseIntegration {
542
785
  private objects;
786
+ private s3;
787
+ private defaultBucket;
788
+ private publicUrlBase;
543
789
  constructor(config: IntegrationConfig);
544
790
  execute(action: string, params: IntegrationParams): Promise<IntegrationResult>;
545
- /** Build a composite key from bucket and object key. */
791
+ private bucketOf;
546
792
  private compositeKey;
547
- /** Generate a deterministic etag from content. */
548
793
  private generateEtag;
549
- /** Compute the byte size of content. */
550
- private computeSize;
794
+ /** Resolve the upload inputs from either admitted shape. */
795
+ private resolveUpload;
796
+ private publicUrl;
551
797
  private upload;
552
798
  private download;
553
799
  private list;
554
800
  private deleteObject;
801
+ private signUrl;
555
802
  private getSignedUrl;
556
803
  }
557
804
 
@@ -658,4 +905,4 @@ declare class ArxivIntegration extends BaseIntegration {
658
905
  private search;
659
906
  }
660
907
 
661
- export { type AlmadarCheckoutSession, type AlmadarCustomer, type AlmadarInvoiceFailure, type AlmadarInvoicePayment, type AlmadarPortalSession, type AlmadarStripeEvent, type AlmadarStripeEventOk, type AlmadarSubscription, type AlmadarSubscriptionStatus, type AlmadarTier, ArxivIntegration, type ArxivResult, BaseIntegration, CLIIntegration, type CancelSubscriptionInput, ConsoleLogger, type CreateCheckoutInput, type CreateCustomerInput, type CreatePortalInput, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, EmailIntegration, IconifyIntegration, IntegrationConfig, type IntegrationConstructor, IntegrationErrorCode, IntegrationLogger, IntegrationParams, IntegrationResult, LLMIntegration, MLIntegration, OAuthIntegration, OtelIntegration, QueueIntegration, RedisIntegration, type RetryConfig, type SqlGuardResult, StorageIntegration, StripeIntegration, type StripePriceMap, TwilioIntegration, type UpdateSubscriptionInput, type VerifyAndParseInput, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, assertReadOnlySelect, getIntegration, getRegisteredIntegrations, isKnownIntegration, registerIntegration, verifyAndParseStripeEvent, withRetry };
908
+ export { AccountingIntegration, type AlmadarCheckoutSession, type AlmadarCustomer, type AlmadarInvoiceFailure, type AlmadarInvoicePayment, type AlmadarPortalSession, type AlmadarStripeEvent, type AlmadarStripeEventOk, type AlmadarSubscription, type AlmadarSubscriptionStatus, type AlmadarTier, ArxivIntegration, type ArxivResult, BankingIntegration, BaseIntegration, CLIIntegration, CalendarIntegration, type CancelSubscriptionInput, ConsoleLogger, type CreateCheckoutInput, type CreateCustomerInput, type CreatePortalInput, CredentialStore, CredentialsIntegration, DatabaseIntegration, DeepAgentIntegration, DockerIntegration, DriveIntegration, EmailIntegration, EsignIntegration, IconifyIntegration, IntegrationConfig, type IntegrationConstructor, IntegrationErrorCode, IntegrationFactory, IntegrationLogger, IntegrationParams, IntegrationResult, LLMIntegration, MLIntegration, MetaAdsIntegration, OAuthIntegration, OtelIntegration, PushIntegration, QueueIntegration, RedisIntegration, type RetryConfig, type SqlGuardResult, StorageIntegration, StripeIntegration, type StripePriceMap, TwilioIntegration, type UpdateSubscriptionInput, type VerifyAndParseInput, WebhookIntegration, WikimediaIntegration, YouTubeIntegration, assertReadOnlySelect, getActiveFactory, getInstalledCredentialStore, getIntegration, getRegisteredIntegrations, googleCalendarHookProvider, installActiveFactory, installCredentialStore, isKnownIntegration, parseCalendarPushNotification, registerIntegration, resolveCredentialRef, uninstallCredentialStore, verifyAndParseStripeEvent, withRetry };