@raisindb/functions-types 0.2.6 → 0.4.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.
- package/package.json +1 -1
- package/raisin.d.ts +179 -0
package/package.json
CHANGED
package/raisin.d.ts
CHANGED
|
@@ -298,6 +298,44 @@ declare namespace raisin {
|
|
|
298
298
|
function diffDays(ts1: number, ts2: number): Promise<number>;
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* One outbound transactional email. The sender is deliberately absent:
|
|
303
|
+
* `from`, the display name and `replyTo` come from the tenant's
|
|
304
|
+
* `/config/email` node, so a function cannot send as an unverified address.
|
|
305
|
+
*/
|
|
306
|
+
interface EmailMessage {
|
|
307
|
+
/** One recipient address, or several. */
|
|
308
|
+
to: string | string[];
|
|
309
|
+
subject: string;
|
|
310
|
+
/** Plain-text body. Always required, even alongside `html`. */
|
|
311
|
+
text: string;
|
|
312
|
+
html?: string;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Proof that the provider accepted a message. Acceptance is not delivery. */
|
|
316
|
+
interface EmailReceipt {
|
|
317
|
+
/** The provider's message id — what a later bounce/webhook correlates to. */
|
|
318
|
+
message_id: string;
|
|
319
|
+
/** The provider that issued it, e.g. "resend" or "brevo". */
|
|
320
|
+
provider: string;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
namespace email {
|
|
324
|
+
/**
|
|
325
|
+
* Send one transactional email through the tenant's configured provider.
|
|
326
|
+
*
|
|
327
|
+
* Every recipient must be allowed by the function's `email_policy`
|
|
328
|
+
* (`{ enabled, allowed_recipients }` in its `.node.yaml`, matched against
|
|
329
|
+
* the recipient DOMAIN); with no block declared the function cannot send,
|
|
330
|
+
* and one disallowed recipient rejects the whole message.
|
|
331
|
+
*
|
|
332
|
+
* Also rejects when email is not configured or not enabled for the tenant,
|
|
333
|
+
* when the function's `secret_policy` does not grant the credential the
|
|
334
|
+
* config references, or when the provider refuses the message.
|
|
335
|
+
*/
|
|
336
|
+
function send(message: EmailMessage): Promise<EmailReceipt>;
|
|
337
|
+
}
|
|
338
|
+
|
|
301
339
|
namespace events {
|
|
302
340
|
function emit(eventType: string, data: any): Promise<void>;
|
|
303
341
|
}
|
|
@@ -393,6 +431,147 @@ declare namespace raisin {
|
|
|
393
431
|
function get(jobIdOrKey: string): Promise<any>;
|
|
394
432
|
}
|
|
395
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Metadata about one secret. Never carries the secret itself — the type has
|
|
436
|
+
* no field that could hold ciphertext or plaintext.
|
|
437
|
+
*/
|
|
438
|
+
interface SecretMetadata {
|
|
439
|
+
name: string;
|
|
440
|
+
/** Human-facing ordinal, from 1. Use it as `secrets.get(name, version)`. */
|
|
441
|
+
version: number;
|
|
442
|
+
/** Which master key sealed it. */
|
|
443
|
+
key_id: number;
|
|
444
|
+
/** RFC 3339. */
|
|
445
|
+
created_at: string;
|
|
446
|
+
created_by: string;
|
|
447
|
+
/** Set only by `rotate`. */
|
|
448
|
+
rotated_at?: string | null;
|
|
449
|
+
/** The node this secret backs, when it is a vaulted schema field. */
|
|
450
|
+
owner_node?: string | null;
|
|
451
|
+
owner_field?: string | null;
|
|
452
|
+
/** True when the newest version is a tombstone. */
|
|
453
|
+
deleted: boolean;
|
|
454
|
+
ciphertext_len: number;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Encrypted secret store, scoped to the current `{tenant, repo, branch}`.
|
|
459
|
+
*
|
|
460
|
+
* **Access is denied by default.** A function reaches these only if its
|
|
461
|
+
* `.node.yaml` declares a matching grant:
|
|
462
|
+
*
|
|
463
|
+
* ```yaml
|
|
464
|
+
* secret_policy:
|
|
465
|
+
* enabled: true
|
|
466
|
+
* allowed_names:
|
|
467
|
+
* - "stripe/*"
|
|
468
|
+
* - "sendgrid_api_key"
|
|
469
|
+
* ```
|
|
470
|
+
*
|
|
471
|
+
* Without one, every call below throws a `policy_denied` error naming the
|
|
472
|
+
* secret. That default is deliberate: adapters run privileged and hold
|
|
473
|
+
* `raisin.http`, so an ungated secrets binding would be a one-line
|
|
474
|
+
* exfiltration path for every credential in the repo.
|
|
475
|
+
*
|
|
476
|
+
* Every method THROWS on failure (denial, missing secret, deleted secret,
|
|
477
|
+
* unconfigured store) — none of them degrade to `null`, which would be
|
|
478
|
+
* indistinguishable from an empty credential.
|
|
479
|
+
*
|
|
480
|
+
* ## The main flow: a secret stored in a node property
|
|
481
|
+
*
|
|
482
|
+
* The common case is not a standalone secret — it is a field on a regular
|
|
483
|
+
* node declared `encrypted: true` in its NodeType. Three steps:
|
|
484
|
+
*
|
|
485
|
+
* 1. The property does not hold the credential. It holds a REFERENCE:
|
|
486
|
+
* `"secret://node/01H8XY.../api_key@1"`.
|
|
487
|
+
* 2. A node read returns that string verbatim. **Reads never resolve** —
|
|
488
|
+
* there is no query flag and no endpoint that returns a value.
|
|
489
|
+
* 3. The function passes the string straight to `get` (or `resolve`):
|
|
490
|
+
*
|
|
491
|
+
* ```javascript
|
|
492
|
+
* const node = await raisin.nodes.get('data', '/connections/stripe');
|
|
493
|
+
* const key = raisin.secrets.get(node.properties.api_key);
|
|
494
|
+
* ```
|
|
495
|
+
*
|
|
496
|
+
* Pass the reference through **as-is**. Do not strip `secret://` or the
|
|
497
|
+
* `@version` suffix yourself: a name may itself contain `@` (an operator
|
|
498
|
+
* name like `ops@example.com`), so only a trailing all-digit run after the
|
|
499
|
+
* LAST `@` is a version. `get` applies that rule using the same parser the
|
|
500
|
+
* storage layer uses.
|
|
501
|
+
*/
|
|
502
|
+
/**
|
|
503
|
+
* Declared as an interface rather than a `namespace`, because `delete` is a
|
|
504
|
+
* reserved word that TypeScript rejects as an ambient `function` name but
|
|
505
|
+
* accepts as an interface method. (The `http`, `nodes` and `admin.nodes`
|
|
506
|
+
* namespaces above still use `function delete(...)`, which does not parse —
|
|
507
|
+
* a pre-existing break, unnoticed because this package has no drift test.)
|
|
508
|
+
*/
|
|
509
|
+
interface SecretsApi {
|
|
510
|
+
/**
|
|
511
|
+
* Read a secret's plaintext.
|
|
512
|
+
*
|
|
513
|
+
* `nameOrRef` is EITHER a bare name (`"stripe_key"`) or a full reference
|
|
514
|
+
* (`"secret://node/01H8XY.../api_key@1"`) — see the three-step flow above
|
|
515
|
+
* for why the reference form is what you will usually be holding.
|
|
516
|
+
*
|
|
517
|
+
* A version pinned in the reference is HONOURED: `secret://k@1` returns
|
|
518
|
+
* version 1, not the latest. That is what makes reading an older node
|
|
519
|
+
* revision give the value that revision actually held.
|
|
520
|
+
*
|
|
521
|
+
* Passing the `version` argument **and** a pinned reference throws. Two
|
|
522
|
+
* stated versions cannot both be satisfied, and silently preferring either
|
|
523
|
+
* could return a value the node revision never held — which is the exact
|
|
524
|
+
* guarantee a pinned reference exists to provide. Pass one or the other;
|
|
525
|
+
* `get('k', 2)` and `get('secret://k', 2)` are both fine.
|
|
526
|
+
*
|
|
527
|
+
* The policy allow-list is matched against the parsed NAME, so both
|
|
528
|
+
* spellings of one secret always get the same allow/deny answer.
|
|
529
|
+
*
|
|
530
|
+
* Throws if the policy denies the name, or the secret is missing or
|
|
531
|
+
* deleted.
|
|
532
|
+
*/
|
|
533
|
+
get(nameOrRef: string, version?: number): Promise<string>;
|
|
534
|
+
/**
|
|
535
|
+
* Resolve a value that MAY be a `secret://` reference.
|
|
536
|
+
*
|
|
537
|
+
* Returns the plaintext when it is one, or the value unchanged when it is
|
|
538
|
+
* not — so a config field that is a literal password on one deployment and
|
|
539
|
+
* a vaulted reference on another is read the same way:
|
|
540
|
+
*
|
|
541
|
+
* ```javascript
|
|
542
|
+
* const password = raisin.secrets.resolve(conn.password);
|
|
543
|
+
* ```
|
|
544
|
+
*
|
|
545
|
+
* A reference that fails to resolve THROWS; it never falls back to
|
|
546
|
+
* returning the reference text, which would send `secret://...` to a
|
|
547
|
+
* provider as a credential. A plain literal is passed through without any
|
|
548
|
+
* policy check, since no secret was touched.
|
|
549
|
+
*/
|
|
550
|
+
resolve(value: string): Promise<string>;
|
|
551
|
+
/**
|
|
552
|
+
* Append a new version. Never overwrites — prior versions stay readable.
|
|
553
|
+
*
|
|
554
|
+
* Accepts a bare name or an UNPINNED reference; a pinned one
|
|
555
|
+
* (`secret://k@1`) is refused, because a write appends a new version
|
|
556
|
+
* rather than replacing that one.
|
|
557
|
+
*/
|
|
558
|
+
put(name: string, value: string): Promise<{ name: string; version: number }>;
|
|
559
|
+
/**
|
|
560
|
+
* Metadata for the newest version of every secret this function may read.
|
|
561
|
+
* Never returns values, and is filtered to the policy's allowed names.
|
|
562
|
+
*/
|
|
563
|
+
list(): Promise<SecretMetadata[]>;
|
|
564
|
+
/**
|
|
565
|
+
* Append a new version stamped as a rotation. Pinned `secret://name@N`
|
|
566
|
+
* references keep resolving to the old version.
|
|
567
|
+
*/
|
|
568
|
+
rotate(name: string, value: string): Promise<{ name: string; version: number }>;
|
|
569
|
+
/** Append a tombstone. Prior versions remain readable by pinned reference. */
|
|
570
|
+
delete(name: string): Promise<{ name: string; version: number }>;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const secrets: SecretsApi;
|
|
574
|
+
|
|
396
575
|
namespace sql {
|
|
397
576
|
function query(sql: string, params: any[]): Promise<any>;
|
|
398
577
|
function execute(sql: string, params: any[]): Promise<number>;
|