@crowi/plugin-api 1.0.0-alpha.6 → 1.0.0-alpha.8

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
@@ -109,6 +109,40 @@ const myPlugin: CrowiPlugin = {
109
109
  export default myPlugin;
110
110
  ```
111
111
 
112
+ ## Post-save connectivity verification (`verifyConfig`)
113
+
114
+ A plugin whose config change needs a real connectivity/permission check (a storage bucket, a search cluster, …) can implement `verifyConfig`. The runtime calls it once after an admin save has already persisted and `reconfigure` has already run — never before, and never as a condition for the save itself:
115
+
116
+ ```ts
117
+ import type { CrowiPlugin, PluginConfigVerificationSnapshot, PluginConfigVerificationOptions, PluginConfigVerificationResult } from '@crowi/plugin-api';
118
+
119
+ const myPlugin: CrowiPlugin = {
120
+ // ...
121
+
122
+ verifyConfig: async (
123
+ snapshot: PluginConfigVerificationSnapshot,
124
+ options: PluginConfigVerificationOptions,
125
+ ): Promise<PluginConfigVerificationResult> => {
126
+ const config = snapshot.config<{ endpoint: string; accessKey: string }>();
127
+ try {
128
+ await probeMyBackend(config);
129
+ return { status: 'ok' };
130
+ } catch (err) {
131
+ return { status: 'failed', reason: classifyMyError(err) };
132
+ }
133
+ },
134
+ };
135
+ ```
136
+
137
+ A few things make this different from every other `register*` / `reconfigure` callback:
138
+
139
+ - **Snapshot, not `PluginContext`.** `verifyConfig` receives a `PluginConfigVerificationSnapshot` — a read-only, point-in-time view of this plugin's own config (and any declared, `exposesConfigToDependents` dependency's config), frozen at the moment the triggering save was about to persist. It is NOT the live `PluginContext`: there is no `setConfig`, `model`, `state`, or `pageMetadata` on it, and calling `snapshot.config()` later never reflects a different admin request's save that lands while your hook is still running.
140
+ - **Fans out to dependents.** If plugin B `requires` plugin A and B implements `verifyConfig`, saving A's config also re-verifies B (same affected-set walk `reconfigure` uses). B's hook only sees A's dependency config if A also set `exposesConfigToDependents: true`.
141
+ - **Non-blocking, always.** A failing (or throwing, or never-resolving) `verifyConfig` never fails the save — the save already succeeded by the time this hook runs. `options.timeoutMs` (currently 10 seconds) is a NOTICE the caller stops waiting on your promise after, not a cancellation signal: there is no `AbortSignal` anywhere in this contract, and none is threaded down into any `StorageDriver` call your hook makes. Design your hook's own I/O with a bounded retry/attempt policy (e.g. a single attempt, no retries) so it settles well within that budget on its own.
142
+ - **Result is a closed, safe union.** Return `{ status: 'ok' }` or `{ status: 'failed', reason }`, where `reason` is one of `'unreachable' | 'auth-failed' | 'resource-missing' | 'write-denied' | 'unknown'`. Never put raw SDK error text, a stack trace, an endpoint, or credential material anywhere in the result (or in anything you log) — the runtime reports this straight to the admin API response. Anything your hook returns outside this shape is normalized to `{ status: 'failed', reason: 'unknown' }` by the caller, so prefer an honest `'unknown'` yourself over guessing a more specific reason you can't actually confirm.
143
+ - **Optional.** A plugin with no `verifyConfig` is completely unaffected — no extra work at boot or save time, no entry in the response's `verificationResults`.
144
+ - **Instance-local, not cluster-wide.** The runtime calls `verifyConfig` on whichever api process handled the save request and reports only that process's outcome. It never coordinates with other replicas, so a result reflects reachability/permissions from that one instance at that moment — not the deployment as a whole. If your hook's I/O (network reachability, IAM/role assumption, DNS) can differ between replicas, document that for operators; don't imply a passing result means every replica can reach the backend.
145
+
112
146
  ## See also
113
147
 
114
148
  - [Plugin development guide](https://crowi.wiki/docs/plugins/developing) —
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod/v3';
2
2
  import { Readable } from 'node:stream';
3
+ import { Configuration } from 'openid-client';
3
4
  import { Context } from 'hono';
4
5
 
5
6
  /**
@@ -206,6 +207,101 @@ interface PluginLogger {
206
207
  error(message: string, ...args: unknown[]): void;
207
208
  }
208
209
 
210
+ /**
211
+ * Contract for `CrowiPlugin.verifyConfig` — a non-blocking, post-save
212
+ * connectivity/permission probe (feature-plugin-config-live-verification).
213
+ * Deliberately its own module, separate from `context.ts`'s live
214
+ * `PluginContext`: a verification hook runs AFTER the admin save has
215
+ * already persisted (and after `reconfigure` has already rebuilt the live
216
+ * driver), against the EXACT values that request saved — not whatever the
217
+ * config cache holds by the time the hook actually runs. Handing a hook
218
+ * `PluginContext` would let it call `ctx.setConfig()` / read a
219
+ * concurrently-updated cache / touch models, none of which a read-only,
220
+ * best-effort probe should be able to do.
221
+ */
222
+ /**
223
+ * Recursively read-only view of `T`. Used for both `config()` and
224
+ * `dependencyConfig()` on {@link PluginConfigVerificationSnapshot} — a
225
+ * verification hook must not be able to mutate the plan's materialized
226
+ * values (they are shared across the plan and, for a dependency, may be
227
+ * read by more than one hook).
228
+ */
229
+ type ReadonlyDeep<T> = T extends readonly (infer U)[] ? readonly ReadonlyDeep<U>[] : T extends object ? {
230
+ readonly [K in keyof T]: ReadonlyDeep<T[K]>;
231
+ } : T;
232
+ /**
233
+ * Immutable facade a `verifyConfig` hook reads its plugin's (and its
234
+ * declared dependencies') config through. NOT `PluginContext`: this
235
+ * snapshot is materialized once, before the save that triggered
236
+ * verification, and never changes for the lifetime of the hook call — a
237
+ * concurrent save of another plugin's config (or of this plugin's config,
238
+ * from a second in-flight admin request) cannot change what an
239
+ * already-running hook sees. See `PluginManager.createVerificationPlan()`.
240
+ */
241
+ interface PluginConfigVerificationSnapshot {
242
+ /**
243
+ * This plugin's own config, as it was — or will be, for the plugin whose
244
+ * save triggered this verification — immediately after the save. Throws
245
+ * if the plugin does not declare a `configSchema` (mirrors
246
+ * `PluginContext.config()`).
247
+ */
248
+ config<T>(): ReadonlyDeep<T>;
249
+ /**
250
+ * A declared dependency's config. Same capability check as
251
+ * `PluginContext.dependencyConfig()`: `dependencyName` must be listed in
252
+ * this plugin's `requires`, AND the dependency must declare
253
+ * `exposesConfigToDependents: true`. Throws otherwise.
254
+ */
255
+ dependencyConfig<T>(dependencyName: string): ReadonlyDeep<T>;
256
+ }
257
+ /**
258
+ * Passed alongside the snapshot to every `verifyConfig` call.
259
+ *
260
+ * `timeoutMs` is a NOTICE, not a cancellation mechanism: the caller
261
+ * (`PluginManager`) stops waiting on the hook's returned promise after
262
+ * this many milliseconds and normalizes the result to
263
+ * `{ status: 'failed', reason: 'unreachable' }`, but it never aborts the
264
+ * hook itself — there is no `AbortSignal` here, and none is passed down to
265
+ * any `StorageDriver` call a storage hook makes (the driver's public `put`
266
+ * / `get` / `delete` contract takes no such option; see
267
+ * `@crowi/plugin-api`'s `registries/storage.ts`). A hook whose underlying
268
+ * I/O is still in flight when the caller gives up keeps running in the
269
+ * background; hooks that touch external resources they created (e.g. a
270
+ * storage probe object) should not rely on ever being told to stop, and
271
+ * should clean up opportunistically rather than assume they'll get to run
272
+ * to completion before anyone stops watching.
273
+ */
274
+ interface PluginConfigVerificationOptions {
275
+ timeoutMs: number;
276
+ }
277
+ /** The closed set of reasons a verification probe can fail for. Anything a driver can't confidently place in one of these falls into `'unknown'` — a wrong specific reason would mislead an operator more than an honest "couldn't tell". */
278
+ type VerificationFailureReason = 'unreachable' | 'auth-failed' | 'resource-missing' | 'write-denied' | 'unknown';
279
+ /**
280
+ * What a `verifyConfig` hook resolves to. Deliberately a closed,
281
+ * allow-listed shape — the caller projects whatever a hook returns onto
282
+ * this union (an invalid shape normalizes to `{ status: 'failed', reason:
283
+ * 'unknown' }`), so a hook can never smuggle raw SDK error text, a stack
284
+ * trace, an endpoint, or credential material into the admin response or
285
+ * logs by returning it as an extra field.
286
+ */
287
+ type PluginConfigVerificationResult = {
288
+ status: 'ok';
289
+ } | {
290
+ status: 'failed';
291
+ reason: VerificationFailureReason;
292
+ };
293
+ /**
294
+ * Key namespace every storage `verifyConfig` probe writes its round-trip
295
+ * object under — deliberately disjoint from `attachment/*` (core's
296
+ * uploaded-file namespace) so a probe object can never collide with,
297
+ * shadow, or get mistaken for a real attachment. A storage hook builds its
298
+ * probe key as `` `${CONFIG_VERIFICATION_KEY_PREFIX}<random>` ``; because
299
+ * cleanup after a probe is best-effort (see the `timeoutMs` note on
300
+ * {@link PluginConfigVerificationOptions}), an operator who finds a
301
+ * leftover object can safely delete anything under this prefix.
302
+ */
303
+ declare const CONFIG_VERIFICATION_KEY_PREFIX = "__crowi_config_verification__/";
304
+
209
305
  /**
210
306
  * Domain events emitted by core. The full event payload shapes live in
211
307
  * `@crowi/server`; this contract publishes only the event names so the
@@ -463,8 +559,8 @@ interface AuthProfile {
463
559
  extra?: Record<string, unknown>;
464
560
  }
465
561
  /**
466
- * Result of `verify` — either a normalised profile (success) or an
467
- * error reason the login UI surfaces.
562
+ * Result of `verify` / `fetchProfile` — either a normalised profile
563
+ * (success) or an error reason the login UI surfaces.
468
564
  */
469
565
  type AuthVerifyResult = {
470
566
  ok: true;
@@ -473,38 +569,166 @@ type AuthVerifyResult = {
473
569
  ok: false;
474
570
  reason: string;
475
571
  };
572
+ /** One field to render on a `credential` driver's sign-in form. */
573
+ interface CredentialField {
574
+ /** Form field name, e.g. `'username'` / `'password'`. */
575
+ name: string;
576
+ /** Human-readable label rendered next to the field. */
577
+ label: string;
578
+ /** Input type. Defaults to `'text'` when omitted. */
579
+ type?: 'text' | 'email' | 'password';
580
+ required?: boolean;
581
+ }
476
582
  /**
477
- * Auth provider driver. The login screen asks core for the list of
478
- * registered drivers and renders one button per driver
479
- * (`Sign in with Google`). Clicking redirects through the plugin's
480
- * registered routes (`/api/plugins/<name>/oauth/start`); the
481
- * provider redirects back to `/api/plugins/<name>/oauth/callback`,
482
- * which the plugin's contract handles.
483
- *
484
- * `verify` is the bridge: given whatever the plugin pulled out of the
485
- * callback (token / code / SAML response), produce a normalised
486
- * `AuthProfile` or a failure reason.
583
+ * Direct-credential auth: the user submits credentials to Crowi itself
584
+ * (LDAP, local password). No redirect, no external IdP round-trip.
487
585
  */
488
- interface AuthDriver {
489
- /**
490
- * Human-readable label for the login button (e.g. `'Google'`).
491
- * Localisation is the plugin's responsibility — i18n keys can be
492
- * resolved by the plugin before registration.
493
- */
586
+ interface CredentialAuthDriver {
587
+ kind: 'credential';
588
+ /** Usually omitted credential drivers render as the sign-in form. */
589
+ buttonLabel?: string;
590
+ /** Fields to render on the sign-in form (e.g. [username, password]). */
591
+ fields: CredentialField[];
592
+ verify(credentials: Record<string, string>): Promise<AuthVerifyResult>;
593
+ }
594
+ /**
595
+ * OAuth 2.0 / OIDC client credentials, read lazily at request time (see
596
+ * `getClientConfig()` below) rather than captured at registration.
597
+ */
598
+ interface OAuthClientConfig {
599
+ clientId: string;
600
+ clientSecret: string;
601
+ }
602
+ /** Token response from an OAuth 2.0 / OIDC token endpoint. */
603
+ interface OAuthTokens {
604
+ accessToken: string;
605
+ tokenType?: string;
606
+ expiresIn?: number;
607
+ refreshToken?: string;
608
+ scope?: string;
609
+ /** Present for an OIDC token response — the raw, still-unverified id_token JWT. */
610
+ idToken?: string;
611
+ }
612
+ /**
613
+ * Redirect/federated auth: the browser bounces to an external IdP using
614
+ * the plain OAuth 2.0 authorization-code flow (no id_token).
615
+ */
616
+ interface OAuth2AuthDriver {
617
+ kind: 'oauth2';
494
618
  buttonLabel: string;
495
- /** Optional icon URL for the login button. */
496
619
  iconUrl?: string;
497
- /**
498
- * Map provider-specific verification data into a normalised profile.
499
- * Called from inside the plugin's own callback route, with whatever
500
- * shape that route extracted. Typed as `unknown` here because the
501
- * shape is plugin-private.
502
- */
503
- verify(verificationData: unknown): Promise<AuthVerifyResult>;
620
+ authorizeUrl: string;
621
+ tokenUrl: string;
622
+ scopes: string[];
623
+ /** Declare when the IdP supports PKCE (S256). */
624
+ pkce?: boolean;
625
+ /**
626
+ * Lazy accessor, evaluated per request — NOT captured at registration.
627
+ * Returns null while the plugin is unconfigured; core then hides the
628
+ * provider from the provider list (enablement) and rejects `/start`.
629
+ * Lazy evaluation is also what makes admin config changes take effect
630
+ * without re-registering the driver.
631
+ */
632
+ getClientConfig(): OAuthClientConfig | null;
633
+ /**
634
+ * Exchange completed; fetch the provider profile and map it. Returns
635
+ * `AuthVerifyResult` so the driver can REJECT after a successful
636
+ * exchange (e.g. an org-membership gate) — a successful exchange does
637
+ * not by itself guarantee a successful sign-in.
638
+ */
639
+ fetchProfile(tokens: OAuthTokens): Promise<AuthVerifyResult>;
504
640
  }
641
+ /** OIDC = OAuth 2.0 + standardised discovery + id_token claims. */
642
+ interface OidcAuthDriver {
643
+ kind: 'oidc';
644
+ buttonLabel: string;
645
+ iconUrl?: string;
646
+ /** `…/.well-known/openid-configuration` */
647
+ discoveryUrl: string;
648
+ /** Default `['openid', 'email', 'profile']`. */
649
+ scopes: string[];
650
+ /** OIDC always uses PKCE. */
651
+ pkce: true;
652
+ /** Same lazy contract as `OAuth2AuthDriver.getClientConfig()`. */
653
+ getClientConfig(): OAuthClientConfig | null;
654
+ /**
655
+ * Resolve (and cache) the `openid-client` `Configuration` for this
656
+ * driver's current credentials. Returns `null` without performing any
657
+ * network I/O while `getClientConfig()` is unconfigured. See the
658
+ * discovery-cache doc comment below for the caching contract.
659
+ */
660
+ getConfiguration(): Promise<Configuration | null>;
661
+ /**
662
+ * Optional policy gate, called after core validates the id_token and
663
+ * before `mapClaims` — the OIDC analogue of `fetchProfile`'s
664
+ * rejection (e.g. a Google Workspace `hd` domain restriction).
665
+ */
666
+ authorize?(claims: Record<string, unknown>): Promise<{
667
+ ok: true;
668
+ } | {
669
+ ok: false;
670
+ reason: string;
671
+ }>;
672
+ /** Optional claim → AuthProfile override; default maps sub/email/name. */
673
+ mapClaims?(claims: Record<string, unknown>): Partial<AuthProfile>;
674
+ }
675
+ /**
676
+ * `'saml'` is reserved (RFC-0014 §9) for a future `SamlAuthDriver` — it is
677
+ * a valid `AuthDriverKind` so downstream code can already discriminate on
678
+ * it, but no `SamlAuthDriver` interface exists yet and `AuthDriver` below
679
+ * does not include it as a member. SAML's required attributes and
680
+ * callback shape are still undecided; adding a member type ahead of that
681
+ * design would let a plugin construct a value with no real runtime.
682
+ */
683
+ type AuthDriverKind = 'credential' | 'oauth2' | 'oidc' | 'saml';
684
+ /**
685
+ * Auth provider driver. The login screen asks core for the list of
686
+ * registered drivers and renders one button per `oauth2`/`oidc` driver
687
+ * (`Sign in with Google`) or one sign-in form per `credential` driver.
688
+ * See RFC-0014 §3 for the full design rationale.
689
+ */
690
+ type AuthDriver = CredentialAuthDriver | OAuth2AuthDriver | OidcAuthDriver;
505
691
  interface AuthRegistry {
506
692
  register(driverName: string, driver: AuthDriver): void;
507
693
  }
694
+ interface CreateOAuth2DriverOptions {
695
+ buttonLabel: string;
696
+ iconUrl?: string;
697
+ authorizeUrl: string;
698
+ tokenUrl: string;
699
+ /** Defaults to `[]` when omitted. */
700
+ scopes?: string[];
701
+ pkce?: boolean;
702
+ getClientConfig(): OAuthClientConfig | null;
703
+ fetchProfile(tokens: OAuthTokens): Promise<AuthVerifyResult>;
704
+ }
705
+ /**
706
+ * Build a plain OAuth 2.0 authorization-code driver. Synchronous, I/O-free
707
+ * — see the module doc comment above.
708
+ */
709
+ declare function createOAuth2Driver(options: CreateOAuth2DriverOptions): OAuth2AuthDriver;
710
+ interface CreateOidcDriverOptions {
711
+ buttonLabel: string;
712
+ iconUrl?: string;
713
+ discoveryUrl: string;
714
+ /** Defaults to `['openid', 'email', 'profile']` when omitted. */
715
+ scopes?: string[];
716
+ getClientConfig(): OAuthClientConfig | null;
717
+ authorize?(claims: Record<string, unknown>): Promise<{
718
+ ok: true;
719
+ } | {
720
+ ok: false;
721
+ reason: string;
722
+ }>;
723
+ mapClaims?(claims: Record<string, unknown>): Partial<AuthProfile>;
724
+ }
725
+ /**
726
+ * Build an OIDC driver. Synchronous, I/O-free at call time — see the
727
+ * module doc comment above. `getConfiguration()` on the returned driver
728
+ * is the only entry point that performs discovery, and only on first use
729
+ * (see `resolveOidcConfiguration` below).
730
+ */
731
+ declare function createOidcDriver(options: CreateOidcDriverOptions): OidcAuthDriver;
508
732
 
509
733
  /**
510
734
  * Notification payload — the runtime-neutral shape passed to every
@@ -1349,6 +1573,26 @@ interface PluginReadinessDeclaration {
1349
1573
  /** `configSchema` field names that must be non-empty for `driver` to actually work once selected. */
1350
1574
  requiredConfigFields: string[];
1351
1575
  }
1576
+ /**
1577
+ * One all-or-nothing group of `configSchema` fields — see
1578
+ * `CrowiPlugin.configAtomicGroups`.
1579
+ */
1580
+ interface PluginConfigAtomicGroup {
1581
+ /**
1582
+ * Stable identifier, part of the physical storage key
1583
+ * (`plugin:<plugin>:__atomic:<name>`). Renaming it orphans the stored
1584
+ * document, so treat it like a migration.
1585
+ */
1586
+ name: string;
1587
+ /** The `configSchema` field names stored together. Non-empty, no duplicates, and each field may belong to only one group. */
1588
+ keys: readonly string[];
1589
+ /**
1590
+ * Encrypt the whole stored group at rest. Set this when ANY member is
1591
+ * secret: the group is one value, so it is either all encrypted or all
1592
+ * not — there is no per-field choice left once they share a document.
1593
+ */
1594
+ sensitive?: boolean;
1595
+ }
1352
1596
  /**
1353
1597
  * The contract every Crowi plugin satisfies. Plugins export their
1354
1598
  * `CrowiPlugin` object as the package's default export; the runtime
@@ -1438,6 +1682,24 @@ interface CrowiPlugin {
1438
1682
  * the field that calls the plugin's contributed REST endpoint.
1439
1683
  */
1440
1684
  configSchema?: z.ZodObject<Record<string, z.ZodTypeAny>>;
1685
+ /**
1686
+ * RFC-0014 phase 4 — `configSchema` fields that must never be visible
1687
+ * to anyone in a half-written state, declared as groups that are stored
1688
+ * as ONE Config document instead of one row per field.
1689
+ *
1690
+ * The motivating case is an OAuth client id + secret. Written as
1691
+ * separate rows, a failure between them leaves the instance advertising
1692
+ * a new client id paired with the previous secret — a configuration
1693
+ * that never existed and cannot authenticate, visible to every replica
1694
+ * until an operator notices. As a single document there is no
1695
+ * in-between: readers see the whole previous pair or the whole new one.
1696
+ *
1697
+ * This is a STORAGE contract, not a general escape hatch for making
1698
+ * arbitrary keys atomic — the fields still appear to the plugin (and to
1699
+ * the admin form) as ordinary flat config, and are only reassembled at
1700
+ * the persistence boundary.
1701
+ */
1702
+ configAtomicGroups?: readonly PluginConfigAtomicGroup[];
1441
1703
  /**
1442
1704
  * Per-Page metadata schema. When set, every Page document has a
1443
1705
  * `metadata['<plugin-name>']` slot whose shape matches this schema,
@@ -1572,6 +1834,39 @@ interface CrowiPlugin {
1572
1834
  * of the very UI they need to fix the misconfiguration.
1573
1835
  */
1574
1836
  reconfigure?: (ctx: PluginContext) => void | Promise<void>;
1837
+ /**
1838
+ * Non-blocking connectivity/permission probe run once, after a save that
1839
+ * touched this plugin's own config OR a dependency's config (any plugin
1840
+ * that has this one in `requires`) has already persisted AND already
1841
+ * run `reconfigure` — feature-plugin-config-live-verification. Never
1842
+ * gates the save: whatever this returns is reported alongside a save
1843
+ * that already succeeded, never rolled back.
1844
+ *
1845
+ * Receives a {@link PluginConfigVerificationSnapshot}, NOT the live
1846
+ * `PluginContext` — do not close over or otherwise reach for `ctx` from
1847
+ * inside this hook. The snapshot is a read-only, point-in-time view
1848
+ * materialized from the exact values the triggering save just wrote (own
1849
+ * config) plus any declared, `exposesConfigToDependents`-opted-in
1850
+ * dependency config — it never reflects a LATER save by a different
1851
+ * admin request, even one that lands while this hook is still running.
1852
+ * `snapshot.config()` / `snapshot.dependencyConfig()` can throw if the
1853
+ * runtime couldn't materialize a value (e.g. an existing, currently
1854
+ * invalid dependency config); the runtime skips calling this hook
1855
+ * entirely in that case rather than invoking it with a broken snapshot.
1856
+ *
1857
+ * `options.timeoutMs` is a notice, not a cancellation signal — see its
1858
+ * doc. Must resolve within that budget or the caller treats it as
1859
+ * `{ status: 'failed', reason: 'unreachable' }`; a promise that keeps
1860
+ * running past that point should still clean up after itself when it
1861
+ * eventually settles, but must never throw out of that cleanup in a way
1862
+ * that becomes an unhandled rejection.
1863
+ *
1864
+ * The returned result (and anything it internally logs) must never
1865
+ * include raw SDK/driver error text, stack traces, endpoints, or
1866
+ * credential material — only the closed `reason` enum. See
1867
+ * `PluginConfigVerificationResult`.
1868
+ */
1869
+ verifyConfig?: (snapshot: PluginConfigVerificationSnapshot, options: PluginConfigVerificationOptions) => Promise<PluginConfigVerificationResult>;
1575
1870
  }
1576
1871
 
1577
1872
  /**
@@ -1763,4 +2058,4 @@ type SanitizeSvgResult = {
1763
2058
  */
1764
2059
  declare function sanitizeSvg(input: string, policy: SanitizeSvgPolicy): SanitizeSvgResult;
1765
2060
 
1766
- export { ACTION_FIELD_MARKER, type AdmissionControlConfig, type AppInfo, type AuthContext, type AuthDriver, type AuthProfile, type AuthRegistry, type AuthVerifyResult, type CacheEntry, type CacheKey, type CacheStorage, type CodeBlockInfo, type CodeBlockRenderer, type CrowiPlugin, type EmailMessage, type EmbedFragment, type EmbedInput, type EmbedRenderer, type EventBus, type InlineExpansion, type MailSender, type MailSenderRegistry, type NodeRenderer, type NotificationPayload, type NotifierDriver, type NotifierRegistry, type PageMetadataAccessor, type PluginContext, type PluginEvents, type PluginLogger, type PluginReadinessDeclaration, type PluginRouteHandler, type PluginRouteMethod, type PluginRouteOptions, type PluginRouterScope, type RenderActor, type RenderContext, type RenderError, type RenderPhase, type RenderResult, type RendererRegistry, type Reservation, SENSITIVE_FIELD_MARKER, type SanitizeSvgPolicy, type SanitizeSvgResult, type ScopedCacheStorage, type SearchDriver, type SearchHit, type SearchHits, type SearchPageType, type SearchQuery, type SearchQueryGrants, type SearchQueryViewer, type SearchRegistry, type SearchableDoc, type StateCell, type StorageDriver, type StoragePutMeta, type StoragePutResult, type StorageRegistry, type StructuredRenderPayload, type UrlInlineExpansionRule, escapeHtml, extractSvgDimensions, getActionAnnotation, isSensitiveField, sanitizeSvg };
2061
+ export { ACTION_FIELD_MARKER, type AdmissionControlConfig, type AppInfo, type AuthContext, type AuthDriver, type AuthDriverKind, type AuthProfile, type AuthRegistry, type AuthVerifyResult, CONFIG_VERIFICATION_KEY_PREFIX, type CacheEntry, type CacheKey, type CacheStorage, type CodeBlockInfo, type CodeBlockRenderer, type CreateOAuth2DriverOptions, type CreateOidcDriverOptions, type CredentialAuthDriver, type CredentialField, type CrowiPlugin, type EmailMessage, type EmbedFragment, type EmbedInput, type EmbedRenderer, type EventBus, type InlineExpansion, type MailSender, type MailSenderRegistry, type NodeRenderer, type NotificationPayload, type NotifierDriver, type NotifierRegistry, type OAuth2AuthDriver, type OAuthClientConfig, type OAuthTokens, type OidcAuthDriver, type PageMetadataAccessor, type PluginConfigAtomicGroup, type PluginConfigVerificationOptions, type PluginConfigVerificationResult, type PluginConfigVerificationSnapshot, type PluginContext, type PluginEvents, type PluginLogger, type PluginReadinessDeclaration, type PluginRouteHandler, type PluginRouteMethod, type PluginRouteOptions, type PluginRouterScope, type ReadonlyDeep, type RenderActor, type RenderContext, type RenderError, type RenderPhase, type RenderResult, type RendererRegistry, type Reservation, SENSITIVE_FIELD_MARKER, type SanitizeSvgPolicy, type SanitizeSvgResult, type ScopedCacheStorage, type SearchDriver, type SearchHit, type SearchHits, type SearchPageType, type SearchQuery, type SearchQueryGrants, type SearchQueryViewer, type SearchRegistry, type SearchableDoc, type StateCell, type StorageDriver, type StoragePutMeta, type StoragePutResult, type StorageRegistry, type StructuredRenderPayload, type UrlInlineExpansionRule, type VerificationFailureReason, createOAuth2Driver, createOidcDriver, escapeHtml, extractSvgDimensions, getActionAnnotation, isSensitiveField, sanitizeSvg };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod/v3';
2
2
  import { Readable } from 'node:stream';
3
+ import { Configuration } from 'openid-client';
3
4
  import { Context } from 'hono';
4
5
 
5
6
  /**
@@ -206,6 +207,101 @@ interface PluginLogger {
206
207
  error(message: string, ...args: unknown[]): void;
207
208
  }
208
209
 
210
+ /**
211
+ * Contract for `CrowiPlugin.verifyConfig` — a non-blocking, post-save
212
+ * connectivity/permission probe (feature-plugin-config-live-verification).
213
+ * Deliberately its own module, separate from `context.ts`'s live
214
+ * `PluginContext`: a verification hook runs AFTER the admin save has
215
+ * already persisted (and after `reconfigure` has already rebuilt the live
216
+ * driver), against the EXACT values that request saved — not whatever the
217
+ * config cache holds by the time the hook actually runs. Handing a hook
218
+ * `PluginContext` would let it call `ctx.setConfig()` / read a
219
+ * concurrently-updated cache / touch models, none of which a read-only,
220
+ * best-effort probe should be able to do.
221
+ */
222
+ /**
223
+ * Recursively read-only view of `T`. Used for both `config()` and
224
+ * `dependencyConfig()` on {@link PluginConfigVerificationSnapshot} — a
225
+ * verification hook must not be able to mutate the plan's materialized
226
+ * values (they are shared across the plan and, for a dependency, may be
227
+ * read by more than one hook).
228
+ */
229
+ type ReadonlyDeep<T> = T extends readonly (infer U)[] ? readonly ReadonlyDeep<U>[] : T extends object ? {
230
+ readonly [K in keyof T]: ReadonlyDeep<T[K]>;
231
+ } : T;
232
+ /**
233
+ * Immutable facade a `verifyConfig` hook reads its plugin's (and its
234
+ * declared dependencies') config through. NOT `PluginContext`: this
235
+ * snapshot is materialized once, before the save that triggered
236
+ * verification, and never changes for the lifetime of the hook call — a
237
+ * concurrent save of another plugin's config (or of this plugin's config,
238
+ * from a second in-flight admin request) cannot change what an
239
+ * already-running hook sees. See `PluginManager.createVerificationPlan()`.
240
+ */
241
+ interface PluginConfigVerificationSnapshot {
242
+ /**
243
+ * This plugin's own config, as it was — or will be, for the plugin whose
244
+ * save triggered this verification — immediately after the save. Throws
245
+ * if the plugin does not declare a `configSchema` (mirrors
246
+ * `PluginContext.config()`).
247
+ */
248
+ config<T>(): ReadonlyDeep<T>;
249
+ /**
250
+ * A declared dependency's config. Same capability check as
251
+ * `PluginContext.dependencyConfig()`: `dependencyName` must be listed in
252
+ * this plugin's `requires`, AND the dependency must declare
253
+ * `exposesConfigToDependents: true`. Throws otherwise.
254
+ */
255
+ dependencyConfig<T>(dependencyName: string): ReadonlyDeep<T>;
256
+ }
257
+ /**
258
+ * Passed alongside the snapshot to every `verifyConfig` call.
259
+ *
260
+ * `timeoutMs` is a NOTICE, not a cancellation mechanism: the caller
261
+ * (`PluginManager`) stops waiting on the hook's returned promise after
262
+ * this many milliseconds and normalizes the result to
263
+ * `{ status: 'failed', reason: 'unreachable' }`, but it never aborts the
264
+ * hook itself — there is no `AbortSignal` here, and none is passed down to
265
+ * any `StorageDriver` call a storage hook makes (the driver's public `put`
266
+ * / `get` / `delete` contract takes no such option; see
267
+ * `@crowi/plugin-api`'s `registries/storage.ts`). A hook whose underlying
268
+ * I/O is still in flight when the caller gives up keeps running in the
269
+ * background; hooks that touch external resources they created (e.g. a
270
+ * storage probe object) should not rely on ever being told to stop, and
271
+ * should clean up opportunistically rather than assume they'll get to run
272
+ * to completion before anyone stops watching.
273
+ */
274
+ interface PluginConfigVerificationOptions {
275
+ timeoutMs: number;
276
+ }
277
+ /** The closed set of reasons a verification probe can fail for. Anything a driver can't confidently place in one of these falls into `'unknown'` — a wrong specific reason would mislead an operator more than an honest "couldn't tell". */
278
+ type VerificationFailureReason = 'unreachable' | 'auth-failed' | 'resource-missing' | 'write-denied' | 'unknown';
279
+ /**
280
+ * What a `verifyConfig` hook resolves to. Deliberately a closed,
281
+ * allow-listed shape — the caller projects whatever a hook returns onto
282
+ * this union (an invalid shape normalizes to `{ status: 'failed', reason:
283
+ * 'unknown' }`), so a hook can never smuggle raw SDK error text, a stack
284
+ * trace, an endpoint, or credential material into the admin response or
285
+ * logs by returning it as an extra field.
286
+ */
287
+ type PluginConfigVerificationResult = {
288
+ status: 'ok';
289
+ } | {
290
+ status: 'failed';
291
+ reason: VerificationFailureReason;
292
+ };
293
+ /**
294
+ * Key namespace every storage `verifyConfig` probe writes its round-trip
295
+ * object under — deliberately disjoint from `attachment/*` (core's
296
+ * uploaded-file namespace) so a probe object can never collide with,
297
+ * shadow, or get mistaken for a real attachment. A storage hook builds its
298
+ * probe key as `` `${CONFIG_VERIFICATION_KEY_PREFIX}<random>` ``; because
299
+ * cleanup after a probe is best-effort (see the `timeoutMs` note on
300
+ * {@link PluginConfigVerificationOptions}), an operator who finds a
301
+ * leftover object can safely delete anything under this prefix.
302
+ */
303
+ declare const CONFIG_VERIFICATION_KEY_PREFIX = "__crowi_config_verification__/";
304
+
209
305
  /**
210
306
  * Domain events emitted by core. The full event payload shapes live in
211
307
  * `@crowi/server`; this contract publishes only the event names so the
@@ -463,8 +559,8 @@ interface AuthProfile {
463
559
  extra?: Record<string, unknown>;
464
560
  }
465
561
  /**
466
- * Result of `verify` — either a normalised profile (success) or an
467
- * error reason the login UI surfaces.
562
+ * Result of `verify` / `fetchProfile` — either a normalised profile
563
+ * (success) or an error reason the login UI surfaces.
468
564
  */
469
565
  type AuthVerifyResult = {
470
566
  ok: true;
@@ -473,38 +569,166 @@ type AuthVerifyResult = {
473
569
  ok: false;
474
570
  reason: string;
475
571
  };
572
+ /** One field to render on a `credential` driver's sign-in form. */
573
+ interface CredentialField {
574
+ /** Form field name, e.g. `'username'` / `'password'`. */
575
+ name: string;
576
+ /** Human-readable label rendered next to the field. */
577
+ label: string;
578
+ /** Input type. Defaults to `'text'` when omitted. */
579
+ type?: 'text' | 'email' | 'password';
580
+ required?: boolean;
581
+ }
476
582
  /**
477
- * Auth provider driver. The login screen asks core for the list of
478
- * registered drivers and renders one button per driver
479
- * (`Sign in with Google`). Clicking redirects through the plugin's
480
- * registered routes (`/api/plugins/<name>/oauth/start`); the
481
- * provider redirects back to `/api/plugins/<name>/oauth/callback`,
482
- * which the plugin's contract handles.
483
- *
484
- * `verify` is the bridge: given whatever the plugin pulled out of the
485
- * callback (token / code / SAML response), produce a normalised
486
- * `AuthProfile` or a failure reason.
583
+ * Direct-credential auth: the user submits credentials to Crowi itself
584
+ * (LDAP, local password). No redirect, no external IdP round-trip.
487
585
  */
488
- interface AuthDriver {
489
- /**
490
- * Human-readable label for the login button (e.g. `'Google'`).
491
- * Localisation is the plugin's responsibility — i18n keys can be
492
- * resolved by the plugin before registration.
493
- */
586
+ interface CredentialAuthDriver {
587
+ kind: 'credential';
588
+ /** Usually omitted credential drivers render as the sign-in form. */
589
+ buttonLabel?: string;
590
+ /** Fields to render on the sign-in form (e.g. [username, password]). */
591
+ fields: CredentialField[];
592
+ verify(credentials: Record<string, string>): Promise<AuthVerifyResult>;
593
+ }
594
+ /**
595
+ * OAuth 2.0 / OIDC client credentials, read lazily at request time (see
596
+ * `getClientConfig()` below) rather than captured at registration.
597
+ */
598
+ interface OAuthClientConfig {
599
+ clientId: string;
600
+ clientSecret: string;
601
+ }
602
+ /** Token response from an OAuth 2.0 / OIDC token endpoint. */
603
+ interface OAuthTokens {
604
+ accessToken: string;
605
+ tokenType?: string;
606
+ expiresIn?: number;
607
+ refreshToken?: string;
608
+ scope?: string;
609
+ /** Present for an OIDC token response — the raw, still-unverified id_token JWT. */
610
+ idToken?: string;
611
+ }
612
+ /**
613
+ * Redirect/federated auth: the browser bounces to an external IdP using
614
+ * the plain OAuth 2.0 authorization-code flow (no id_token).
615
+ */
616
+ interface OAuth2AuthDriver {
617
+ kind: 'oauth2';
494
618
  buttonLabel: string;
495
- /** Optional icon URL for the login button. */
496
619
  iconUrl?: string;
497
- /**
498
- * Map provider-specific verification data into a normalised profile.
499
- * Called from inside the plugin's own callback route, with whatever
500
- * shape that route extracted. Typed as `unknown` here because the
501
- * shape is plugin-private.
502
- */
503
- verify(verificationData: unknown): Promise<AuthVerifyResult>;
620
+ authorizeUrl: string;
621
+ tokenUrl: string;
622
+ scopes: string[];
623
+ /** Declare when the IdP supports PKCE (S256). */
624
+ pkce?: boolean;
625
+ /**
626
+ * Lazy accessor, evaluated per request — NOT captured at registration.
627
+ * Returns null while the plugin is unconfigured; core then hides the
628
+ * provider from the provider list (enablement) and rejects `/start`.
629
+ * Lazy evaluation is also what makes admin config changes take effect
630
+ * without re-registering the driver.
631
+ */
632
+ getClientConfig(): OAuthClientConfig | null;
633
+ /**
634
+ * Exchange completed; fetch the provider profile and map it. Returns
635
+ * `AuthVerifyResult` so the driver can REJECT after a successful
636
+ * exchange (e.g. an org-membership gate) — a successful exchange does
637
+ * not by itself guarantee a successful sign-in.
638
+ */
639
+ fetchProfile(tokens: OAuthTokens): Promise<AuthVerifyResult>;
504
640
  }
641
+ /** OIDC = OAuth 2.0 + standardised discovery + id_token claims. */
642
+ interface OidcAuthDriver {
643
+ kind: 'oidc';
644
+ buttonLabel: string;
645
+ iconUrl?: string;
646
+ /** `…/.well-known/openid-configuration` */
647
+ discoveryUrl: string;
648
+ /** Default `['openid', 'email', 'profile']`. */
649
+ scopes: string[];
650
+ /** OIDC always uses PKCE. */
651
+ pkce: true;
652
+ /** Same lazy contract as `OAuth2AuthDriver.getClientConfig()`. */
653
+ getClientConfig(): OAuthClientConfig | null;
654
+ /**
655
+ * Resolve (and cache) the `openid-client` `Configuration` for this
656
+ * driver's current credentials. Returns `null` without performing any
657
+ * network I/O while `getClientConfig()` is unconfigured. See the
658
+ * discovery-cache doc comment below for the caching contract.
659
+ */
660
+ getConfiguration(): Promise<Configuration | null>;
661
+ /**
662
+ * Optional policy gate, called after core validates the id_token and
663
+ * before `mapClaims` — the OIDC analogue of `fetchProfile`'s
664
+ * rejection (e.g. a Google Workspace `hd` domain restriction).
665
+ */
666
+ authorize?(claims: Record<string, unknown>): Promise<{
667
+ ok: true;
668
+ } | {
669
+ ok: false;
670
+ reason: string;
671
+ }>;
672
+ /** Optional claim → AuthProfile override; default maps sub/email/name. */
673
+ mapClaims?(claims: Record<string, unknown>): Partial<AuthProfile>;
674
+ }
675
+ /**
676
+ * `'saml'` is reserved (RFC-0014 §9) for a future `SamlAuthDriver` — it is
677
+ * a valid `AuthDriverKind` so downstream code can already discriminate on
678
+ * it, but no `SamlAuthDriver` interface exists yet and `AuthDriver` below
679
+ * does not include it as a member. SAML's required attributes and
680
+ * callback shape are still undecided; adding a member type ahead of that
681
+ * design would let a plugin construct a value with no real runtime.
682
+ */
683
+ type AuthDriverKind = 'credential' | 'oauth2' | 'oidc' | 'saml';
684
+ /**
685
+ * Auth provider driver. The login screen asks core for the list of
686
+ * registered drivers and renders one button per `oauth2`/`oidc` driver
687
+ * (`Sign in with Google`) or one sign-in form per `credential` driver.
688
+ * See RFC-0014 §3 for the full design rationale.
689
+ */
690
+ type AuthDriver = CredentialAuthDriver | OAuth2AuthDriver | OidcAuthDriver;
505
691
  interface AuthRegistry {
506
692
  register(driverName: string, driver: AuthDriver): void;
507
693
  }
694
+ interface CreateOAuth2DriverOptions {
695
+ buttonLabel: string;
696
+ iconUrl?: string;
697
+ authorizeUrl: string;
698
+ tokenUrl: string;
699
+ /** Defaults to `[]` when omitted. */
700
+ scopes?: string[];
701
+ pkce?: boolean;
702
+ getClientConfig(): OAuthClientConfig | null;
703
+ fetchProfile(tokens: OAuthTokens): Promise<AuthVerifyResult>;
704
+ }
705
+ /**
706
+ * Build a plain OAuth 2.0 authorization-code driver. Synchronous, I/O-free
707
+ * — see the module doc comment above.
708
+ */
709
+ declare function createOAuth2Driver(options: CreateOAuth2DriverOptions): OAuth2AuthDriver;
710
+ interface CreateOidcDriverOptions {
711
+ buttonLabel: string;
712
+ iconUrl?: string;
713
+ discoveryUrl: string;
714
+ /** Defaults to `['openid', 'email', 'profile']` when omitted. */
715
+ scopes?: string[];
716
+ getClientConfig(): OAuthClientConfig | null;
717
+ authorize?(claims: Record<string, unknown>): Promise<{
718
+ ok: true;
719
+ } | {
720
+ ok: false;
721
+ reason: string;
722
+ }>;
723
+ mapClaims?(claims: Record<string, unknown>): Partial<AuthProfile>;
724
+ }
725
+ /**
726
+ * Build an OIDC driver. Synchronous, I/O-free at call time — see the
727
+ * module doc comment above. `getConfiguration()` on the returned driver
728
+ * is the only entry point that performs discovery, and only on first use
729
+ * (see `resolveOidcConfiguration` below).
730
+ */
731
+ declare function createOidcDriver(options: CreateOidcDriverOptions): OidcAuthDriver;
508
732
 
509
733
  /**
510
734
  * Notification payload — the runtime-neutral shape passed to every
@@ -1349,6 +1573,26 @@ interface PluginReadinessDeclaration {
1349
1573
  /** `configSchema` field names that must be non-empty for `driver` to actually work once selected. */
1350
1574
  requiredConfigFields: string[];
1351
1575
  }
1576
+ /**
1577
+ * One all-or-nothing group of `configSchema` fields — see
1578
+ * `CrowiPlugin.configAtomicGroups`.
1579
+ */
1580
+ interface PluginConfigAtomicGroup {
1581
+ /**
1582
+ * Stable identifier, part of the physical storage key
1583
+ * (`plugin:<plugin>:__atomic:<name>`). Renaming it orphans the stored
1584
+ * document, so treat it like a migration.
1585
+ */
1586
+ name: string;
1587
+ /** The `configSchema` field names stored together. Non-empty, no duplicates, and each field may belong to only one group. */
1588
+ keys: readonly string[];
1589
+ /**
1590
+ * Encrypt the whole stored group at rest. Set this when ANY member is
1591
+ * secret: the group is one value, so it is either all encrypted or all
1592
+ * not — there is no per-field choice left once they share a document.
1593
+ */
1594
+ sensitive?: boolean;
1595
+ }
1352
1596
  /**
1353
1597
  * The contract every Crowi plugin satisfies. Plugins export their
1354
1598
  * `CrowiPlugin` object as the package's default export; the runtime
@@ -1438,6 +1682,24 @@ interface CrowiPlugin {
1438
1682
  * the field that calls the plugin's contributed REST endpoint.
1439
1683
  */
1440
1684
  configSchema?: z.ZodObject<Record<string, z.ZodTypeAny>>;
1685
+ /**
1686
+ * RFC-0014 phase 4 — `configSchema` fields that must never be visible
1687
+ * to anyone in a half-written state, declared as groups that are stored
1688
+ * as ONE Config document instead of one row per field.
1689
+ *
1690
+ * The motivating case is an OAuth client id + secret. Written as
1691
+ * separate rows, a failure between them leaves the instance advertising
1692
+ * a new client id paired with the previous secret — a configuration
1693
+ * that never existed and cannot authenticate, visible to every replica
1694
+ * until an operator notices. As a single document there is no
1695
+ * in-between: readers see the whole previous pair or the whole new one.
1696
+ *
1697
+ * This is a STORAGE contract, not a general escape hatch for making
1698
+ * arbitrary keys atomic — the fields still appear to the plugin (and to
1699
+ * the admin form) as ordinary flat config, and are only reassembled at
1700
+ * the persistence boundary.
1701
+ */
1702
+ configAtomicGroups?: readonly PluginConfigAtomicGroup[];
1441
1703
  /**
1442
1704
  * Per-Page metadata schema. When set, every Page document has a
1443
1705
  * `metadata['<plugin-name>']` slot whose shape matches this schema,
@@ -1572,6 +1834,39 @@ interface CrowiPlugin {
1572
1834
  * of the very UI they need to fix the misconfiguration.
1573
1835
  */
1574
1836
  reconfigure?: (ctx: PluginContext) => void | Promise<void>;
1837
+ /**
1838
+ * Non-blocking connectivity/permission probe run once, after a save that
1839
+ * touched this plugin's own config OR a dependency's config (any plugin
1840
+ * that has this one in `requires`) has already persisted AND already
1841
+ * run `reconfigure` — feature-plugin-config-live-verification. Never
1842
+ * gates the save: whatever this returns is reported alongside a save
1843
+ * that already succeeded, never rolled back.
1844
+ *
1845
+ * Receives a {@link PluginConfigVerificationSnapshot}, NOT the live
1846
+ * `PluginContext` — do not close over or otherwise reach for `ctx` from
1847
+ * inside this hook. The snapshot is a read-only, point-in-time view
1848
+ * materialized from the exact values the triggering save just wrote (own
1849
+ * config) plus any declared, `exposesConfigToDependents`-opted-in
1850
+ * dependency config — it never reflects a LATER save by a different
1851
+ * admin request, even one that lands while this hook is still running.
1852
+ * `snapshot.config()` / `snapshot.dependencyConfig()` can throw if the
1853
+ * runtime couldn't materialize a value (e.g. an existing, currently
1854
+ * invalid dependency config); the runtime skips calling this hook
1855
+ * entirely in that case rather than invoking it with a broken snapshot.
1856
+ *
1857
+ * `options.timeoutMs` is a notice, not a cancellation signal — see its
1858
+ * doc. Must resolve within that budget or the caller treats it as
1859
+ * `{ status: 'failed', reason: 'unreachable' }`; a promise that keeps
1860
+ * running past that point should still clean up after itself when it
1861
+ * eventually settles, but must never throw out of that cleanup in a way
1862
+ * that becomes an unhandled rejection.
1863
+ *
1864
+ * The returned result (and anything it internally logs) must never
1865
+ * include raw SDK/driver error text, stack traces, endpoints, or
1866
+ * credential material — only the closed `reason` enum. See
1867
+ * `PluginConfigVerificationResult`.
1868
+ */
1869
+ verifyConfig?: (snapshot: PluginConfigVerificationSnapshot, options: PluginConfigVerificationOptions) => Promise<PluginConfigVerificationResult>;
1575
1870
  }
1576
1871
 
1577
1872
  /**
@@ -1763,4 +2058,4 @@ type SanitizeSvgResult = {
1763
2058
  */
1764
2059
  declare function sanitizeSvg(input: string, policy: SanitizeSvgPolicy): SanitizeSvgResult;
1765
2060
 
1766
- export { ACTION_FIELD_MARKER, type AdmissionControlConfig, type AppInfo, type AuthContext, type AuthDriver, type AuthProfile, type AuthRegistry, type AuthVerifyResult, type CacheEntry, type CacheKey, type CacheStorage, type CodeBlockInfo, type CodeBlockRenderer, type CrowiPlugin, type EmailMessage, type EmbedFragment, type EmbedInput, type EmbedRenderer, type EventBus, type InlineExpansion, type MailSender, type MailSenderRegistry, type NodeRenderer, type NotificationPayload, type NotifierDriver, type NotifierRegistry, type PageMetadataAccessor, type PluginContext, type PluginEvents, type PluginLogger, type PluginReadinessDeclaration, type PluginRouteHandler, type PluginRouteMethod, type PluginRouteOptions, type PluginRouterScope, type RenderActor, type RenderContext, type RenderError, type RenderPhase, type RenderResult, type RendererRegistry, type Reservation, SENSITIVE_FIELD_MARKER, type SanitizeSvgPolicy, type SanitizeSvgResult, type ScopedCacheStorage, type SearchDriver, type SearchHit, type SearchHits, type SearchPageType, type SearchQuery, type SearchQueryGrants, type SearchQueryViewer, type SearchRegistry, type SearchableDoc, type StateCell, type StorageDriver, type StoragePutMeta, type StoragePutResult, type StorageRegistry, type StructuredRenderPayload, type UrlInlineExpansionRule, escapeHtml, extractSvgDimensions, getActionAnnotation, isSensitiveField, sanitizeSvg };
2061
+ export { ACTION_FIELD_MARKER, type AdmissionControlConfig, type AppInfo, type AuthContext, type AuthDriver, type AuthDriverKind, type AuthProfile, type AuthRegistry, type AuthVerifyResult, CONFIG_VERIFICATION_KEY_PREFIX, type CacheEntry, type CacheKey, type CacheStorage, type CodeBlockInfo, type CodeBlockRenderer, type CreateOAuth2DriverOptions, type CreateOidcDriverOptions, type CredentialAuthDriver, type CredentialField, type CrowiPlugin, type EmailMessage, type EmbedFragment, type EmbedInput, type EmbedRenderer, type EventBus, type InlineExpansion, type MailSender, type MailSenderRegistry, type NodeRenderer, type NotificationPayload, type NotifierDriver, type NotifierRegistry, type OAuth2AuthDriver, type OAuthClientConfig, type OAuthTokens, type OidcAuthDriver, type PageMetadataAccessor, type PluginConfigAtomicGroup, type PluginConfigVerificationOptions, type PluginConfigVerificationResult, type PluginConfigVerificationSnapshot, type PluginContext, type PluginEvents, type PluginLogger, type PluginReadinessDeclaration, type PluginRouteHandler, type PluginRouteMethod, type PluginRouteOptions, type PluginRouterScope, type ReadonlyDeep, type RenderActor, type RenderContext, type RenderError, type RenderPhase, type RenderResult, type RendererRegistry, type Reservation, SENSITIVE_FIELD_MARKER, type SanitizeSvgPolicy, type SanitizeSvgResult, type ScopedCacheStorage, type SearchDriver, type SearchHit, type SearchHits, type SearchPageType, type SearchQuery, type SearchQueryGrants, type SearchQueryViewer, type SearchRegistry, type SearchableDoc, type StateCell, type StorageDriver, type StoragePutMeta, type StoragePutResult, type StorageRegistry, type StructuredRenderPayload, type UrlInlineExpansionRule, type VerificationFailureReason, createOAuth2Driver, createOidcDriver, escapeHtml, extractSvgDimensions, getActionAnnotation, isSensitiveField, sanitizeSvg };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,13 +17,24 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
23
33
  ACTION_FIELD_MARKER: () => ACTION_FIELD_MARKER,
34
+ CONFIG_VERIFICATION_KEY_PREFIX: () => CONFIG_VERIFICATION_KEY_PREFIX,
24
35
  SENSITIVE_FIELD_MARKER: () => SENSITIVE_FIELD_MARKER,
36
+ createOAuth2Driver: () => createOAuth2Driver,
37
+ createOidcDriver: () => createOidcDriver,
25
38
  escapeHtml: () => escapeHtml,
26
39
  extractSvgDimensions: () => extractSvgDimensions,
27
40
  getActionAnnotation: () => getActionAnnotation,
@@ -30,6 +43,9 @@ __export(index_exports, {
30
43
  });
31
44
  module.exports = __toCommonJS(index_exports);
32
45
 
46
+ // src/config-verification.ts
47
+ var CONFIG_VERIFICATION_KEY_PREFIX = "__crowi_config_verification__/";
48
+
33
49
  // src/html.ts
34
50
  function escapeHtml(s) {
35
51
  return s.replace(/[&<>"']/g, (c) => {
@@ -50,6 +66,117 @@ function escapeHtml(s) {
50
66
  });
51
67
  }
52
68
 
69
+ // src/registries/auth.ts
70
+ var import_node_crypto = require("crypto");
71
+ function assertNonEmptyString(value, label, factory) {
72
+ if (value.trim() === "") {
73
+ throw new TypeError(`${factory}: '${label}' must be a non-empty string.`);
74
+ }
75
+ }
76
+ function assertValidUrl(value, label, factory) {
77
+ try {
78
+ new URL(value);
79
+ } catch {
80
+ throw new TypeError(`${factory}: '${label}' must be a valid URL, got '${value}'.`);
81
+ }
82
+ }
83
+ function assertNonEmptyScopes(scopes, factory) {
84
+ for (const scope of scopes) {
85
+ assertNonEmptyString(scope, "scopes[]", factory);
86
+ }
87
+ }
88
+ function createOAuth2Driver(options) {
89
+ const FACTORY = "createOAuth2Driver";
90
+ assertNonEmptyString(options.buttonLabel, "buttonLabel", FACTORY);
91
+ assertValidUrl(options.authorizeUrl, "authorizeUrl", FACTORY);
92
+ assertValidUrl(options.tokenUrl, "tokenUrl", FACTORY);
93
+ const scopes = options.scopes ?? [];
94
+ assertNonEmptyScopes(scopes, FACTORY);
95
+ return {
96
+ kind: "oauth2",
97
+ buttonLabel: options.buttonLabel,
98
+ iconUrl: options.iconUrl,
99
+ authorizeUrl: options.authorizeUrl,
100
+ tokenUrl: options.tokenUrl,
101
+ scopes,
102
+ pkce: options.pkce,
103
+ getClientConfig: options.getClientConfig,
104
+ fetchProfile: options.fetchProfile
105
+ };
106
+ }
107
+ var DEFAULT_OIDC_SCOPES = ["openid", "email", "profile"];
108
+ function createOidcDriver(options) {
109
+ const FACTORY = "createOidcDriver";
110
+ assertNonEmptyString(options.buttonLabel, "buttonLabel", FACTORY);
111
+ assertValidUrl(options.discoveryUrl, "discoveryUrl", FACTORY);
112
+ const scopes = options.scopes ?? [...DEFAULT_OIDC_SCOPES];
113
+ assertNonEmptyScopes(scopes, FACTORY);
114
+ return {
115
+ kind: "oidc",
116
+ buttonLabel: options.buttonLabel,
117
+ iconUrl: options.iconUrl,
118
+ discoveryUrl: options.discoveryUrl,
119
+ scopes,
120
+ pkce: true,
121
+ getClientConfig: options.getClientConfig,
122
+ getConfiguration: () => resolveOidcConfiguration(options.discoveryUrl, options.getClientConfig),
123
+ authorize: options.authorize,
124
+ mapClaims: options.mapClaims
125
+ };
126
+ }
127
+ var DISCOVERY_CACHE_TTL_MS = 5 * 60 * 1e3;
128
+ var DISCOVERY_CACHE_MAX_ENTRIES = 64;
129
+ var discoveryCache = /* @__PURE__ */ new Map();
130
+ var inFlightDiscoveries = /* @__PURE__ */ new Map();
131
+ function discoveryCacheKey(discoveryUrl, clientId, clientSecret) {
132
+ const secretFingerprint = (0, import_node_crypto.createHash)("sha256").update(clientSecret).digest("hex");
133
+ return (0, import_node_crypto.createHash)("sha256").update(`${discoveryUrl}\0${clientId}\0${secretFingerprint}`).digest("hex");
134
+ }
135
+ function evictOldestDiscoveryCacheEntry() {
136
+ let oldestKey;
137
+ let oldestExpiresAt = Number.POSITIVE_INFINITY;
138
+ for (const [key, entry] of discoveryCache) {
139
+ if (entry.expiresAt < oldestExpiresAt) {
140
+ oldestExpiresAt = entry.expiresAt;
141
+ oldestKey = key;
142
+ }
143
+ }
144
+ if (oldestKey !== void 0) {
145
+ discoveryCache.delete(oldestKey);
146
+ }
147
+ }
148
+ function cacheDiscoveryResult(key, configuration) {
149
+ if (!discoveryCache.has(key) && discoveryCache.size >= DISCOVERY_CACHE_MAX_ENTRIES) {
150
+ evictOldestDiscoveryCacheEntry();
151
+ }
152
+ discoveryCache.set(key, { configuration, expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS });
153
+ }
154
+ async function resolveOidcConfiguration(discoveryUrl, getClientConfig) {
155
+ const clientConfig = getClientConfig();
156
+ if (clientConfig == null) return null;
157
+ const { clientId, clientSecret } = clientConfig;
158
+ const key = discoveryCacheKey(discoveryUrl, clientId, clientSecret);
159
+ const cached = discoveryCache.get(key);
160
+ if (cached !== void 0) {
161
+ if (cached.expiresAt > Date.now()) return cached.configuration;
162
+ discoveryCache.delete(key);
163
+ }
164
+ const inFlight = inFlightDiscoveries.get(key);
165
+ if (inFlight !== void 0) return inFlight;
166
+ const discoveryPromise = (async () => {
167
+ const { discovery } = await import("openid-client");
168
+ const configuration = await discovery(new URL(discoveryUrl), clientId, clientSecret);
169
+ cacheDiscoveryResult(key, configuration);
170
+ return configuration;
171
+ })();
172
+ inFlightDiscoveries.set(key, discoveryPromise);
173
+ try {
174
+ return await discoveryPromise;
175
+ } finally {
176
+ inFlightDiscoveries.delete(key);
177
+ }
178
+ }
179
+
53
180
  // src/schema-markers.ts
54
181
  var SENSITIVE_FIELD_MARKER = "@sensitive";
55
182
  var ACTION_FIELD_MARKER = "@action";
@@ -272,7 +399,10 @@ function cssUnescape(css) {
272
399
  // Annotate the CommonJS export names for ESM import in node:
273
400
  0 && (module.exports = {
274
401
  ACTION_FIELD_MARKER,
402
+ CONFIG_VERIFICATION_KEY_PREFIX,
275
403
  SENSITIVE_FIELD_MARKER,
404
+ createOAuth2Driver,
405
+ createOidcDriver,
276
406
  escapeHtml,
277
407
  extractSvgDimensions,
278
408
  getActionAnnotation,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/html.ts","../src/schema-markers.ts","../../svg-sanitize/src/dimensions.ts","../../svg-sanitize/src/sanitize.ts"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config-verification.ts","../src/html.ts","../src/registries/auth.ts","../src/schema-markers.ts","../../svg-sanitize/src/dimensions.ts","../../svg-sanitize/src/sanitize.ts"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -1,3 +1,6 @@
1
+ // src/config-verification.ts
2
+ var CONFIG_VERIFICATION_KEY_PREFIX = "__crowi_config_verification__/";
3
+
1
4
  // src/html.ts
2
5
  function escapeHtml(s) {
3
6
  return s.replace(/[&<>"']/g, (c) => {
@@ -18,6 +21,117 @@ function escapeHtml(s) {
18
21
  });
19
22
  }
20
23
 
24
+ // src/registries/auth.ts
25
+ import { createHash } from "crypto";
26
+ function assertNonEmptyString(value, label, factory) {
27
+ if (value.trim() === "") {
28
+ throw new TypeError(`${factory}: '${label}' must be a non-empty string.`);
29
+ }
30
+ }
31
+ function assertValidUrl(value, label, factory) {
32
+ try {
33
+ new URL(value);
34
+ } catch {
35
+ throw new TypeError(`${factory}: '${label}' must be a valid URL, got '${value}'.`);
36
+ }
37
+ }
38
+ function assertNonEmptyScopes(scopes, factory) {
39
+ for (const scope of scopes) {
40
+ assertNonEmptyString(scope, "scopes[]", factory);
41
+ }
42
+ }
43
+ function createOAuth2Driver(options) {
44
+ const FACTORY = "createOAuth2Driver";
45
+ assertNonEmptyString(options.buttonLabel, "buttonLabel", FACTORY);
46
+ assertValidUrl(options.authorizeUrl, "authorizeUrl", FACTORY);
47
+ assertValidUrl(options.tokenUrl, "tokenUrl", FACTORY);
48
+ const scopes = options.scopes ?? [];
49
+ assertNonEmptyScopes(scopes, FACTORY);
50
+ return {
51
+ kind: "oauth2",
52
+ buttonLabel: options.buttonLabel,
53
+ iconUrl: options.iconUrl,
54
+ authorizeUrl: options.authorizeUrl,
55
+ tokenUrl: options.tokenUrl,
56
+ scopes,
57
+ pkce: options.pkce,
58
+ getClientConfig: options.getClientConfig,
59
+ fetchProfile: options.fetchProfile
60
+ };
61
+ }
62
+ var DEFAULT_OIDC_SCOPES = ["openid", "email", "profile"];
63
+ function createOidcDriver(options) {
64
+ const FACTORY = "createOidcDriver";
65
+ assertNonEmptyString(options.buttonLabel, "buttonLabel", FACTORY);
66
+ assertValidUrl(options.discoveryUrl, "discoveryUrl", FACTORY);
67
+ const scopes = options.scopes ?? [...DEFAULT_OIDC_SCOPES];
68
+ assertNonEmptyScopes(scopes, FACTORY);
69
+ return {
70
+ kind: "oidc",
71
+ buttonLabel: options.buttonLabel,
72
+ iconUrl: options.iconUrl,
73
+ discoveryUrl: options.discoveryUrl,
74
+ scopes,
75
+ pkce: true,
76
+ getClientConfig: options.getClientConfig,
77
+ getConfiguration: () => resolveOidcConfiguration(options.discoveryUrl, options.getClientConfig),
78
+ authorize: options.authorize,
79
+ mapClaims: options.mapClaims
80
+ };
81
+ }
82
+ var DISCOVERY_CACHE_TTL_MS = 5 * 60 * 1e3;
83
+ var DISCOVERY_CACHE_MAX_ENTRIES = 64;
84
+ var discoveryCache = /* @__PURE__ */ new Map();
85
+ var inFlightDiscoveries = /* @__PURE__ */ new Map();
86
+ function discoveryCacheKey(discoveryUrl, clientId, clientSecret) {
87
+ const secretFingerprint = createHash("sha256").update(clientSecret).digest("hex");
88
+ return createHash("sha256").update(`${discoveryUrl}\0${clientId}\0${secretFingerprint}`).digest("hex");
89
+ }
90
+ function evictOldestDiscoveryCacheEntry() {
91
+ let oldestKey;
92
+ let oldestExpiresAt = Number.POSITIVE_INFINITY;
93
+ for (const [key, entry] of discoveryCache) {
94
+ if (entry.expiresAt < oldestExpiresAt) {
95
+ oldestExpiresAt = entry.expiresAt;
96
+ oldestKey = key;
97
+ }
98
+ }
99
+ if (oldestKey !== void 0) {
100
+ discoveryCache.delete(oldestKey);
101
+ }
102
+ }
103
+ function cacheDiscoveryResult(key, configuration) {
104
+ if (!discoveryCache.has(key) && discoveryCache.size >= DISCOVERY_CACHE_MAX_ENTRIES) {
105
+ evictOldestDiscoveryCacheEntry();
106
+ }
107
+ discoveryCache.set(key, { configuration, expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS });
108
+ }
109
+ async function resolveOidcConfiguration(discoveryUrl, getClientConfig) {
110
+ const clientConfig = getClientConfig();
111
+ if (clientConfig == null) return null;
112
+ const { clientId, clientSecret } = clientConfig;
113
+ const key = discoveryCacheKey(discoveryUrl, clientId, clientSecret);
114
+ const cached = discoveryCache.get(key);
115
+ if (cached !== void 0) {
116
+ if (cached.expiresAt > Date.now()) return cached.configuration;
117
+ discoveryCache.delete(key);
118
+ }
119
+ const inFlight = inFlightDiscoveries.get(key);
120
+ if (inFlight !== void 0) return inFlight;
121
+ const discoveryPromise = (async () => {
122
+ const { discovery } = await import("openid-client");
123
+ const configuration = await discovery(new URL(discoveryUrl), clientId, clientSecret);
124
+ cacheDiscoveryResult(key, configuration);
125
+ return configuration;
126
+ })();
127
+ inFlightDiscoveries.set(key, discoveryPromise);
128
+ try {
129
+ return await discoveryPromise;
130
+ } finally {
131
+ inFlightDiscoveries.delete(key);
132
+ }
133
+ }
134
+
21
135
  // src/schema-markers.ts
22
136
  var SENSITIVE_FIELD_MARKER = "@sensitive";
23
137
  var ACTION_FIELD_MARKER = "@action";
@@ -239,7 +353,10 @@ function cssUnescape(css) {
239
353
  }
240
354
  export {
241
355
  ACTION_FIELD_MARKER,
356
+ CONFIG_VERIFICATION_KEY_PREFIX,
242
357
  SENSITIVE_FIELD_MARKER,
358
+ createOAuth2Driver,
359
+ createOidcDriver,
243
360
  escapeHtml,
244
361
  extractSvgDimensions,
245
362
  getActionAnnotation,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/html.ts","../src/schema-markers.ts","../../svg-sanitize/src/dimensions.ts","../../svg-sanitize/src/sanitize.ts"],"mappings":";AAaO,SAAS,WAAW,GAAmB;AAC5C,SAAO,EAAE,QAAQ,YAAY,CAAC,MAAM;AAClC,YAAQ,GAAG;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF,CAAC;AACH;;;ACNO,IAAM,yBAAyB;AAa/B,IAAM,sBAAsB;AAQ5B,SAAS,iBAAiB,OAA8B;AAC7D,QAAM,cAAc,MAAM;AAC1B,SAAO,OAAO,gBAAgB,YAAY,YAAY,UAAU,EAAE,WAAW,sBAAsB;AACrG;AA6BO,SAAS,oBAAoB,OAA8C;AAChF,QAAM,cAAc,MAAM;AAC1B,MAAI,OAAO,gBAAgB,SAAU,QAAO;AAC5C,QAAM,UAAU,YAAY,UAAU;AACtC,MAAI,CAAC,QAAQ,WAAW,mBAAmB,EAAG,QAAO;AAErD,QAAM,OAAO,QAAQ,MAAM,oBAAoB,MAAM,EAAE,UAAU;AAEjE,QAAM,QAAQ,KAAK,MAAM,mCAAmC;AAC5D,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,CAAC,EAAE,OAAO,QAAQ,IAAI,IAAI;AAChC,SAAO,EAAE,OAAO,QAA8C,KAAK;AACrE;;;AEzFA,SAAS,WAAW,qBAAqB;ADqBzC,IAAM,mBAAmB;AAElB,SAAS,qBAAqB,KAAuD;AAC1F,QAAM,QAAQ,uFAAuF,KAAK,GAAG;AAC7G,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,KAAK,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;AACzC,QAAM,SAAS,KAAK,MAAM,OAAO,MAAM,CAAC,CAAC,CAAC;AAC1C,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AAChE,MAAI,SAAS,KAAK,UAAU,KAAK,QAAQ,oBAAoB,SAAS,iBAAkB,QAAO;AAC/F,SAAO,EAAE,OAAO,OAAO;AACzB;AC+CO,SAAS,YAAY,OAAe,QAA8C;AACvF,QAAM,MAAM,SAAS,KAAK;AAC1B,MAAI,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAEtD,MAAI,IAAI,SAAS;AAKf,WAAO,EAAE,IAAI,OAAO,QAAQ,sBAAsB;EACpD;AACA,QAAM,OAAO,IAAI;AACjB,MAAI,CAAC,uBAAuB,IAAI,GAAG;AACjC,WAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;EAChD;AAEA,sBAAoB,MAAM,QAAQ,IAAI;AAEtC,QAAM,aAAa,IAAI,cAAc;AACrC,QAAM,aAAa,WAAW,kBAAkB,IAAI;AAOpD,QAAM,YAAY,SAAS,UAAU;AACrC,MAAI,CAAC,aAAa,CAAC,uBAAuB,UAAU,eAAe,GAAG;AACpE,WAAO,EAAE,IAAI,OAAO,QAAQ,uCAAuC;EACrE;AAEA,SAAO,EAAE,IAAI,MAAM,KAAK,WAAW;AACrC;AAEA,IAAM,oBAAoB;AAW1B,IAAM,oBAAoB;AAU1B,IAAM,sBAAsB;AAgB5B,SAAS,sBAAsB,IAAsB;AACnD,SAAO,GAAG,iBAAiB,qBAAqB,GAAG,UAAU;AAC/D;AAUA,SAAS,uBAAuB,IAA+C;AAC7E,SAAO,MAAM,QAAQ,GAAG,cAAc,SAAS,sBAAsB,EAAE;AACzE;AAWA,SAAS,SAAS,QAAgB;AAChC,MAAI;AACF,WAAO,IAAI,UAAU,EAAE,SAAS,MAAM,OAAU,CAAC,EAAE,gBAAgB,QAAQ,eAAe;EAC5F,QAAQ;AACN,WAAO;EACT;AACF;AAWA,IAAM,mBAAmB,oBAAI,IAAI;EAC/B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF,CAAC;AAED,IAAM,8BAA8B;AACpC,IAAM,eAAe;AAErB,SAAS,oBAAoB,IAAa,QAA2B,QAAuB;AAC1F,qBAAmB,IAAI,QAAQ,MAAM;AAErC,MAAI,GAAG,cAAc,SAAS;AAG5B,OAAG,cAAc,kBAAkB,GAAG,eAAe,EAAE;AACvD;EACF;AAEA,aAAW,SAAS,MAAM,KAAK,GAAG,UAAU,GAAG;AAC7C,QAAI,MAAM,aAAa,6BAA6B;AAClD,SAAG,YAAY,KAAK;AACpB;IACF;AACA,QAAI,MAAM,aAAa,aAAc;AACrC,UAAM,UAAU;AAMhB,QAAI,CAAC,sBAAsB,OAAO,KAAK,CAAC,iBAAiB,IAAI,QAAQ,aAAa,QAAQ,QAAQ,GAAG;AACnG,SAAG,YAAY,OAAO;AACtB;IACF;AACA,wBAAoB,SAAS,QAAQ,KAAK;EAC5C;AACF;AAEA,SAAS,mBAAmB,IAAa,QAA2B,QAAuB;AACzF,aAAW,QAAQ,MAAM,KAAK,GAAG,UAAU,GAAG;AAC5C,UAAM,YAAY,KAAK,aAAa,KAAK;AACzC,QAAI,OAAO,KAAK,SAAS,GAAG;AAC1B,SAAG,oBAAoB,IAAI;AAC3B;IACF;AACA,QAAI,cAAc,SAAS;AACzB,SAAG,oBAAoB,IAAI;AAC3B;IACF;AACA,QAAI,cAAc,UAAU,KAAK,iBAAiB,mBAAmB;AAcnE,SAAG,oBAAoB,IAAI;AAC3B;IACF;AACA,QAAI,cAAc,QAAQ;AACxB,YAAM,iBAAiB,kBAAkB,KAAK,OAAO,MAAM;AAC3D,UAAI,mBAAmB,MAAM;AAC3B,WAAG,oBAAoB,IAAI;MAC7B,OAAO;AACL,aAAK,QAAQ;MACf;AACA;IACF;AACA,QAAI,8BAA8B,IAAI,SAAS,GAAG;AAChD,UAAI,CAAC,iBAAiB,KAAK,KAAK,GAAG;AACjC,WAAG,oBAAoB,IAAI;MAC7B;AACA;IACF;AACA,QAAI,KAAK,SAAS,WAAW,KAAK,KAAK,WAAW,QAAQ,GAAG;AAC3D,UAAI,CAAC,UAAU,CAAC,oCAAoC,IAAI,GAAG;AACzD,WAAG,oBAAoB,IAAI;MAC7B;IACF;EACF;AACF;AAoBA,SAAS,oCAAoC,MAAqB;AAChE,MAAI,KAAK,SAAS,QAAS,QAAO;AAClC,SAAO,KAAK,SAAS,iBAAiB,KAAK,UAAU;AACvD;AAQA,IAAM,gCAAgC,oBAAI,IAAI;EAC5C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACF,CAAC;AAED,IAAM,mBAAmB;AAWzB,SAAS,iBAAiB,UAA2B;AAOnD,QAAM,UAAU,MAAM,KAAK,YAAY,QAAQ,EAAE,SAAS,gBAAgB,CAAC;AAC3E,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,QAAQ,MAAM,CAAC,CAAC,EAAE,EAAE,MAAM,MAAM,OAAO,KAAK,EAAE,WAAW,GAAG,CAAC;AACtE;AAGA,SAAS,kBAAkB,UAAkB,QAA0C;AACrF,QAAM,QAAQ,SAAS,KAAK;AAC5B,MAAI,MAAM,WAAW,GAAG,EAAG,QAAO;AAClC,MAAI,gBAAgB,KAAK,KAAK,EAAG,QAAO;AACxC,MAAI,UAAU,KAAK,KAAK,EAAG,QAAO;AAClC,MAAI,MAAM,WAAW,IAAI,EAAG,QAAO;AACnC,MAAI,OAAO,iBAAiB,eAAe,KAAK,KAAK,EAAG,QAAO;AAC/D,SAAO;AACT;AA6CA,SAAS,kBAAkB,KAAqB;AAM9C,QAAM,kBAAkB,IAAI,QAAQ,qBAAqB,GAAG;AAC5D,MAAI,MAAM,YAAY,eAAe;AACrC,QAAM,IAAI,QAAQ,sBAAsB,EAAE;AAC1C,QAAM,IAAI,QAAQ,kBAAkB,CAAC,OAAO,QAAQ,WAAY,OAAO,KAAK,EAAE,WAAW,GAAG,IAAI,QAAQ,MAAO;AAC/G,SAAO;AACT;AAaA,SAAS,YAAY,KAAqB;AACxC,SAAO,IAAI,QAAQ,uDAAuD,CAAC,QAAQ,KAAyB,YAAgC;AAC1I,QAAI,QAAQ,QAAW;AACrB,YAAM,YAAY,OAAO,SAAS,KAAK,EAAE;AACzC,UAAI,cAAc,KAAK,YAAY,WAAa,aAAa,SAAU,aAAa,MAAS,QAAO;AACpG,aAAO,OAAO,cAAc,SAAS;IACvC;AACA,QAAI,YAAY,OAAW,QAAO;AAClC,WAAO;EACT,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../src/config-verification.ts","../src/html.ts","../src/registries/auth.ts","../src/schema-markers.ts","../../svg-sanitize/src/dimensions.ts","../../svg-sanitize/src/sanitize.ts"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowi/plugin-api",
3
- "version": "1.0.0-alpha.6",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "Type-only contract for Crowi 2.0 plugins. See docs/rfcs/0001-plugin-architecture.md.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -41,7 +41,8 @@
41
41
  "@crowi/tsconfig": "0.1.0-alpha.0"
42
42
  },
43
43
  "dependencies": {
44
- "@xmldom/xmldom": "^0.9.10"
44
+ "@xmldom/xmldom": "^0.9.10",
45
+ "openid-client": "^6.8.4"
45
46
  },
46
47
  "scripts": {
47
48
  "build": "tsup",