@janssenproject/cedarling_wasm 0.0.466 → 0.0.467-nodejs

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/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # Cedarling WASM
2
2
 
3
- This module is designed to build cedarling for browser wasm.
3
+ This module builds Cedarling's Rust implementation for WebAssembly. This guide
4
+ covers building and testing the generated binding and running its local browser
5
+ examples; JavaScript package consumers should use the npm package guide below.
6
+
7
+ ## Choose the right guide
8
+
9
+ - For a JavaScript or TypeScript application, use the
10
+ [npm package guide](./js/README.md).
11
+ - For package generation, artifact qualification, and release maintenance, use
12
+ the [maintainer guide](./js/docs/maintainer.md).
13
+ - This guide covers direct development with the wasm-pack-generated binding.
4
14
 
5
15
  ## Building
6
16
 
@@ -55,563 +65,23 @@ async function main() {
55
65
  let instance = await init(BOOTSTRAP_CONFIG);
56
66
  // authorize calls take the request as a JSON string: it crosses the
57
67
  // JS/WASM boundary as one string copy parsed by serde_json
58
- let result = await instance.authorize_unsigned(JSON.stringify(REQUEST_UNSIGNED));
68
+ let result = await instance.authorizeUnsigned(JSON.stringify(REQUEST_UNSIGNED));
59
69
  console.log("result:", result);
60
70
  }
61
71
  main().catch(console.error);
62
72
  ```
63
73
 
64
- Before using any function from library you need initialize WASM runtime by calling `initWasm` function.
65
-
66
- ### Defined API
67
-
68
- ```ts
69
- /**
70
- * Create a new instance of the Cedarling application.
71
- * This function can take as config parameter the eather `Map` other `Object`
72
- */
73
- export function init(config: any): Promise<Cedarling>;
74
-
75
- /**
76
- * Create a new instance of the Cedarling application from archive bytes.
77
- *
78
- * This function allows loading a policy store from a Cedar Archive (.cjar)
79
- * that was fetched with custom logic (e.g., with authentication headers).
80
- *
81
- * # Arguments
82
- * * `config` - Bootstrap configuration (Map or Object). Policy store config is ignored.
83
- * * `archive_bytes` - The .cjar archive bytes (Uint8Array)
84
- *
85
- * # Example
86
- * ```javascript
87
- * const response = await fetch(url, { headers: { Authorization: 'Bearer ...' } });
88
- * const bytes = new Uint8Array(await response.arrayBuffer());
89
- * const cedarling = await init_from_archive_bytes(config, bytes);
90
- * ```
91
- */
92
- export function init_from_archive_bytes(config: any, archive_bytes: Uint8Array): Promise<Cedarling>;
93
-
94
- /**
95
- * The instance of the Cedarling application.
96
- */
97
- export class Cedarling {
98
- /**
99
- * Create a new instance of the Cedarling application.
100
- * Assume that config is `Object`
101
- */
102
- static new(config: object): Promise<Cedarling>;
103
- /**
104
- * Create a new instance of the Cedarling application.
105
- * Assume that config is `Map`
106
- */
107
- static new_from_map(config: Map<any, any>): Promise<Cedarling>;
108
- /**
109
- * Authorize an unsigned request carrying an optional single principal.
110
- * Makes an authorization decision based on the [`RequestUnsigned`].
111
- * When `principal` is omitted / `null` the core uses Cedar partial evaluation;
112
- * residual-dependent requests fail closed with `Decision::Deny` and surface
113
- * residual policy ids in `response.diagnostics.reason`.
114
- */
115
- authorize_unsigned(request: string): Promise<AuthorizeResult>;
116
- /**
117
- * Authorize multi-issuer request.
118
- * Makes authorization decision based on multiple JWT tokens from different issuers
119
- * The request is passed as a JSON string.
120
- */
121
- authorize_multi_issuer(request: string): Promise<MultiIssuerAuthorizeResult>;
122
- /**
123
- * Get logs and remove them from the storage.
124
- * Returns `Array` of `Map`
125
- */
126
- pop_logs(): Array<any>;
127
- /**
128
- * Get specific log entry.
129
- * Returns `Map` with values or `null`.
130
- */
131
- get_log_by_id(id: string): any;
132
- /**
133
- * Returns a list of all log ids.
134
- * Returns `Array` of `String`
135
- */
136
- get_log_ids(): Array<any>;
137
- /**
138
- * Get logs by tag, like `log_kind` or `log level`.
139
- * Tag can be `log_kind`, `log_level`.
140
- */
141
- get_logs_by_tag(tag: string): any[];
142
- /**
143
- * Get logs by request_id.
144
- * Return log entries that match the given request_id.
145
- */
146
- get_logs_by_request_id(request_id: string): any[];
147
- /**
148
- * Get log by request_id and tag, like composite key `request_id` + `log_kind`.
149
- * Tag can be `log_kind`, `log_level`.
150
- * Return log entries that match the given request_id and tag.
151
- */
152
- get_logs_by_request_id_and_tag(request_id: string, tag: string): any[];
153
- /**
154
- * Push a value into the data store with an optional TTL.
155
- * If the key already exists, the value will be replaced.
156
- * If TTL is not provided, the default TTL from configuration is used.
157
- *
158
- * # Arguments
159
- * * `key` - The key for the data entry
160
- * * `value` - The value to store (any JSON-serializable value)
161
- * * `ttl_secs` - Optional TTL in seconds (undefined uses default from config)
162
- *
163
- * # Example
164
- * ```javascript
165
- * cedarling.push_data_ctx("user:123", { name: "John", age: 30 }, 3600);
166
- * cedarling.push_data_ctx("config", { setting: "value" }); // Uses default TTL
167
- * ```
168
- */
169
- push_data_ctx(key: string, value: any, ttl_secs?: number): void;
170
- /**
171
- * Get a value from the data store by key.
172
- * Returns null if the key doesn't exist or the entry has expired.
173
- *
174
- * # Arguments
175
- * * `key` - The key to retrieve
176
- *
177
- * # Example
178
- * ```javascript
179
- * const value = cedarling.get_data_ctx("user:123");
180
- * if (value) {
181
- * console.log(value.name);
182
- * }
183
- * ```
184
- */
185
- get_data_ctx(key: string): any;
186
- /**
187
- * Get a data entry with full metadata by key.
188
- * Returns null if the key doesn't exist or the entry has expired.
189
- * Includes metadata like creation time, expiration, access count, and type.
190
- *
191
- * # Arguments
192
- * * `key` - The key to retrieve
193
- *
194
- * # Example
195
- * ```javascript
196
- * const entry = cedarling.get_data_entry_ctx("user:123");
197
- * if (entry) {
198
- * console.log(`Created: ${entry.created_at}, Access count: ${entry.access_count}`);
199
- * }
200
- * ```
201
- */
202
- get_data_entry_ctx(key: string): any;
203
- /**
204
- * Remove a value from the data store by key.
205
- * Returns true if the key existed and was removed, false otherwise.
206
- *
207
- * # Arguments
208
- * * `key` - The key to remove
209
- *
210
- * # Example
211
- * ```javascript
212
- * const removed = cedarling.remove_data_ctx("user:123");
213
- * ```
214
- */
215
- remove_data_ctx(key: string): boolean;
216
- /**
217
- * Clear all entries from the data store.
218
- *
219
- * # Example
220
- * ```javascript
221
- * cedarling.clear_data_ctx();
222
- * ```
223
- */
224
- clear_data_ctx(): void;
225
- /**
226
- * List all entries with their metadata.
227
- * Returns an array of data entries containing key, value, type, and timing metadata.
228
- *
229
- * # Example
230
- * ```javascript
231
- * const entries = cedarling.list_data_ctx();
232
- * entries.forEach(entry => {
233
- * console.log(`Key: ${entry.key}, Type: ${entry.data_type}`);
234
- * });
235
- * ```
236
- */
237
- list_data_ctx(): any[];
238
- /**
239
- * Get statistics about the data store.
240
- * Returns current entry count, capacity limits, and configuration state.
241
- *
242
- * # Example
243
- * ```javascript
244
- * const stats = cedarling.get_stats_ctx();
245
- * console.log(`Entries: ${stats.entry_count}/${stats.max_entries}`);
246
- * ```
247
- */
248
- get_stats_ctx(): DataStoreStats;
249
- /**
250
- * Trusted issuer loading status helpers.
251
- */
252
- is_trusted_issuer_loaded_by_name(issuer_id: string): boolean;
253
- is_trusted_issuer_loaded_by_iss(iss_claim: string): boolean;
254
- total_issuers(): number;
255
- loaded_trusted_issuers_count(): number;
256
- loaded_trusted_issuer_ids(): Array<string>;
257
- failed_trusted_issuer_ids(): Array<string>;
258
- }
259
-
260
- /**
261
- * A WASM wrapper for the Rust `cedarling::AuthorizeResult` struct.
262
- * Represents the result of an authorization request.
263
- */
264
- export class AuthorizeResult {
265
- /**
266
- * Convert `AuthorizeResult` to json string value
267
- */
268
- json_string(): string;
269
- /**
270
- * Cedar authorization response for the request.
271
- */
272
- response: AuthorizeResultResponse;
273
- /**
274
- * Result of authorization
275
- * true means `ALLOW`
276
- * false means `Deny`
277
- *
278
- * this field is [`bool`] type to be compatible with [authzen Access Evaluation Decision](https://openid.github.io/authzen/#section-6.2.1).
279
- */
280
- decision: boolean;
281
- /**
282
- * Request ID of the authorization request
283
- */
284
- request_id: string;
285
- }
286
-
287
- /**
288
- * A WASM wrapper for the Rust `cedarling::MultiIssuerAuthorizeResult` struct.
289
- * Represents the result of a multi-issuer authorization request.
290
- */
291
- export class MultiIssuerAuthorizeResult {
292
- /**
293
- * Convert `MultiIssuerAuthorizeResult` to json string value
294
- */
295
- json_string(): string;
296
- /**
297
- * Result of Cedar policy authorization
298
- */
299
- response: AuthorizeResultResponse;
300
- /**
301
- * Result of authorization
302
- * true means `ALLOW`
303
- * false means `Deny`
304
- */
305
- decision: boolean;
306
- /**
307
- * Request ID of the authorization request
308
- */
309
- request_id: string;
310
- }
311
-
312
- /**
313
- * A WASM wrapper for the Rust `cedar_policy::Response` struct.
314
- * Represents the result of an authorization request.
315
- */
316
- export class AuthorizeResultResponse {
317
- /**
318
- * Authorization decision
319
- */
320
- readonly decision: boolean;
321
- /**
322
- * Diagnostics providing more information on how this decision was reached
323
- */
324
- readonly diagnostics: Diagnostics;
325
- }
326
-
327
- /**
328
- * Diagnostics
329
- * ===========
330
- *
331
- * Provides detailed information about how a policy decision was made, including policies that contributed to the decision and any errors encountered during evaluation.
332
- */
333
- export class Diagnostics {
334
- /**
335
- * `PolicyId`s of the policies that contributed to the decision.
336
- * If no policies applied to the request, this set will be empty.
337
- *
338
- * The ids should be treated as unordered,
339
- */
340
- readonly reason: string[];
341
- /**
342
- * Errors that occurred during authorization. The errors should be
343
- * treated as unordered, since policies may be evaluated in any order.
344
- */
345
- readonly errors: PolicyEvaluationError[];
346
- }
347
-
348
- /**
349
- * PolicyEvaluationError
350
- * =====================
351
- *
352
- * Represents an error that occurred when evaluating a Cedar policy.
353
- */
354
- export class PolicyEvaluationError {
355
- /**
356
- * Id of the policy with an error
357
- */
358
- readonly id: string;
359
- /**
360
- * Underlying evaluation error string representation
361
- */
362
- readonly error: string;
363
- }
364
-
365
- /**
366
- * DataStoreStats
367
- * ==============
368
- *
369
- * Statistics about the DataStore, providing insight into the current state
370
- * and usage of the data store, including memory usage metrics and capacity information.
371
- */
372
- export class DataStoreStats {
373
- /**
374
- * Number of entries currently stored
375
- */
376
- readonly entry_count: number;
377
- /**
378
- * Maximum number of entries allowed (0 = unlimited)
379
- */
380
- readonly max_entries: number;
381
- /**
382
- * Maximum size per entry in bytes (0 = unlimited)
383
- */
384
- readonly max_entry_size: number;
385
- /**
386
- * Whether metrics tracking is enabled
387
- */
388
- readonly metrics_enabled: boolean;
389
- /**
390
- * Total size of all entries in bytes (approximate, based on JSON serialization)
391
- */
392
- readonly total_size_bytes: number;
393
- /**
394
- * Average size per entry in bytes (0 if no entries)
395
- */
396
- readonly avg_entry_size_bytes: number;
397
- /**
398
- * Percentage of capacity used (0.0-100.0, based on entry count)
399
- */
400
- readonly capacity_usage_percent: number;
401
- /**
402
- * Memory usage threshold percentage (from config)
403
- */
404
- readonly memory_alert_threshold: number;
405
- /**
406
- * Whether memory usage exceeds the alert threshold
407
- */
408
- readonly memory_alert_triggered: boolean;
409
- }
410
- ```
411
-
412
- ## Configuration
413
-
414
- ### Policy Store Sources
415
-
416
- Cedarling supports multiple ways to load policy stores. **In WASM environments, only URL-based loading is available** (no filesystem access).
417
-
418
- #### WASM-Supported Options
419
-
420
- ```javascript
421
- // Option 1: Fetch policy store from URL (simple)
422
- const BOOTSTRAP_CONFIG = {
423
- CEDARLING_POLICY_STORE_URI: "https://example.com/policy-store.cjar",
424
- // Optional: re-fetch every 60s and atomically swap on change.
425
- // Default is 0 (load-once-at-startup). See "Refreshing the policy store"
426
- // in docs/cedarling/reference/cedarling-properties.md for details.
427
- CEDARLING_POLICY_STORE_REFRESH_INTERVAL: 60,
428
- // ... other config
429
- };
430
- const cedarling = await init(BOOTSTRAP_CONFIG);
431
-
432
- // Option 2: Inline JSON string (for embedded policy stores)
433
- // policyStoreJson is the policy store JSON as a string
434
- // See: https://docs.jans.io/stable/cedarling/reference/cedarling-policy-store/
435
- const policyStoreJson = '{"cedar_version":"4.0","policy_stores":{...}}';
436
- const BOOTSTRAP_CONFIG = {
437
- CEDARLING_POLICY_STORE_LOCAL: policyStoreJson,
438
- // ... other config
439
- };
440
- const cedarling = await init(BOOTSTRAP_CONFIG);
441
-
442
- // Option 3: Custom fetch with auth headers (use init_from_archive_bytes)
443
- const response = await fetch("https://example.com/policy-store.cjar", {
444
- headers: { Authorization: `Bearer ${token}` },
445
- });
446
- const bytes = new Uint8Array(await response.arrayBuffer());
447
- const cedarling = await init_from_archive_bytes(BOOTSTRAP_CONFIG, bytes);
448
- ```
449
-
450
- > **Note:** Directory-based loading and file-based loading are **NOT supported in WASM** (no filesystem access). Use URL-based loading or `init_from_archive_bytes` for custom fetch scenarios.
451
-
452
- #### Cedar Archive (.cjar) Format
453
-
454
- For the new directory-based format in WASM, package the directory structure as a `.cjar` file (ZIP archive):
455
-
456
- ```bash
457
- cd policy-store && zip -r ../policy-store.cjar .
458
- ```
459
-
460
- See [Policy Store Formats](../../../docs/cedarling/reference/cedarling-policy-store.md#policy-store-formats) for details on the directory structure and metadata.json format.
461
-
462
- ### Testing Configuration
463
-
464
- For testing scenarios, you may want to disable JWT validation. You can configure this in your bootstrap configuration:
465
-
466
- ```javascript
467
- const BOOTSTRAP_CONFIG = {
468
- CEDARLING_JWT_SIG_VALIDATION: "disabled",
469
- CEDARLING_JWT_STATUS_VALIDATION: "disabled",
470
- };
471
- ```
472
-
473
- For complete configuration documentation, see [cedarling-properties.md](../../../docs/cedarling/cedarling-properties.md) or on [our page](https://docs.jans.io/stable/cedarling/cedarling-properties/).
474
-
475
- ## Context Data API
476
-
477
- The Context Data API allows you to push external data into the Cedarling evaluation context, making it available in Cedar policies through the `context.data` namespace.
478
-
479
- ### Push Data
480
-
481
- Store data with an optional TTL (Time To Live):
482
-
483
- ```javascript
484
- // Push data without TTL (uses default from config)
485
- cedarling.push_data_ctx("user:123", {
486
- role: ["admin", "editor"],
487
- country: "US"
488
- });
489
-
490
- // Push data with TTL (5 minutes = 300 seconds)
491
- cedarling.push_data_ctx("config:app", { setting: "value" }, 300);
492
-
493
- // Push different data types
494
- cedarling.push_data_ctx("key1", "string_value");
495
- cedarling.push_data_ctx("key2", 42);
496
- cedarling.push_data_ctx("key3", [1, 2, 3]);
497
- cedarling.push_data_ctx("key4", { nested: "data" });
498
- ```
499
-
500
- ### Get Data
501
-
502
- Retrieve stored data:
503
-
504
- ```javascript
505
- // Get data by key
506
- const value = cedarling.get_data_ctx("user:123");
507
- if (value) {
508
- console.log(`User roles: ${value.role}`);
509
- }
510
- ```
511
-
512
- ### Get Data Entry with Metadata
513
-
514
- Get a data entry with full metadata including creation time, expiration, access count, and type:
515
-
516
- ```javascript
517
- const entry = cedarling.get_data_entry_ctx("user:123");
518
- if (entry) {
519
- console.log(`Key: ${entry.key}`);
520
- console.log(`Created at: ${entry.created_at}`);
521
- console.log(`Access count: ${entry.access_count}`);
522
- console.log(`Data type: ${entry.data_type}`);
523
- console.log(`Value:`, entry.value);
524
- }
525
- ```
526
-
527
- ### Remove Data
528
-
529
- Remove a specific entry:
530
-
531
- ```javascript
532
- // Remove data by key
533
- const removed = cedarling.remove_data_ctx("user:123");
534
- if (removed) {
535
- console.log("Entry was removed");
536
- } else {
537
- console.log("Entry did not exist");
538
- }
539
- ```
540
-
541
- ### Clear All Data
542
-
543
- Remove all entries from the data store:
544
-
545
- ```javascript
546
- cedarling.clear_data_ctx();
547
- ```
548
-
549
- ### List All Data
550
-
551
- List all entries with their metadata:
552
-
553
- ```javascript
554
- const entries = cedarling.list_data_ctx();
555
- entries.forEach(entry => {
556
- console.log(`Key: ${entry.key}, Type: ${entry.data_type}, Created: ${entry.created_at}`);
557
- });
558
- ```
559
-
560
- ### Get Statistics
561
-
562
- Get statistics about the data store:
563
-
564
- ```javascript
565
- const stats = cedarling.get_stats_ctx();
566
- console.log(`Entries: ${stats.entry_count}/${stats.max_entries}`);
567
- console.log(`Total size: ${stats.total_size_bytes} bytes`);
568
- console.log(`Capacity usage: ${stats.capacity_usage_percent}%`);
569
- ```
570
-
571
- ### Error Handling
572
-
573
- The Context Data API methods throw errors for different error conditions:
574
-
575
- ```javascript
576
- try {
577
- cedarling.push_data_ctx("", { data: "value" }); // Empty key
578
- } catch (error) {
579
- if (error.message.includes("InvalidKey")) {
580
- console.log("Invalid key provided");
581
- }
582
- }
583
-
584
- const value = cedarling.get_data_ctx("nonexistent");
585
- if (value === null) {
586
- console.log("Key not found");
587
- }
588
- ```
589
-
590
- ### Using Data in Cedar Policies
74
+ When importing the generated glue directly from `pkg/`, call `initWasm()` before
75
+ using the binding. The npm package's automatic entries handle this initialization.
591
76
 
592
- Data pushed via the Context Data API is automatically available in Cedar policies under the `context.data` namespace:
77
+ ## API contract
593
78
 
594
- ```cedar
595
- permit(
596
- principal,
597
- action == Action::"read",
598
- resource
599
- ) when {
600
- context.data["user:123"].role.contains("admin")
601
- };
602
- ```
603
-
604
- The data is injected into the evaluation context before policy evaluation, allowing policies to make decisions based on dynamically pushed data.
605
-
606
- ## Trusted Issuer Loading Info
79
+ `pkg/cedarling_wasm.d.ts` is the authoritative direct WebAssembly API after a
80
+ successful build. Callable JavaScript APIs use camelCase, including
81
+ `jsonString()`. Cedarling bootstrap properties, request JSON keys, and returned
82
+ data fields retain their canonical names, including snake_case fields such as
83
+ `request_id`.
607
84
 
608
- When a policy store contains `trusted-issuers/` entries, you can inspect loading status:
609
-
610
- ```javascript
611
- const loaded = cedarling.is_trusted_issuer_loaded_by_name("issuer_id");
612
- const loadedByIss = cedarling.is_trusted_issuer_loaded_by_iss("https://issuer.example.org");
613
- const total = cedarling.total_issuers();
614
- const loadedCount = cedarling.loaded_trusted_issuers_count();
615
- const loadedIds = cedarling.loaded_trusted_issuer_ids();
616
- const failedIds = cedarling.failed_trusted_issuer_ids();
617
- ```
85
+ For portable npm consumption across browser, Node.js ESM, Node.js CommonJS,
86
+ edge, and manual bundler paths, use `@janssenproject/cedarling_wasm` and its
87
+ consumer guide instead of importing files under `pkg/`.