@backstage/backend-plugin-api 1.1.1 → 1.2.0-next.1

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/dist/index.d.ts CHANGED
@@ -1,647 +1,541 @@
1
1
  /// <reference types="node" />
2
- import { Readable } from 'stream';
3
- import { Config } from '@backstage/config';
4
2
  import { JsonObject, HumanDuration, JsonValue } from '@backstage/types';
5
- import { Duration } from 'luxon';
6
- import { Handler, Request, Response } from 'express';
7
- import { PermissionAttributes, EvaluatorRequestOptions, PermissionEvaluator, AuthorizePermissionRequest, AuthorizePermissionResponse, QueryPermissionRequest, QueryPermissionResponse } from '@backstage/plugin-permission-common';
3
+ import { Request, Response, Handler } from 'express';
4
+ import { PermissionAttributes, EvaluatorRequestOptions, PermissionEvaluator, AuthorizePermissionRequest, AuthorizePermissionResponse, QueryPermissionRequest, QueryPermissionResponse, Permission } from '@backstage/plugin-permission-common';
8
5
  import { Knex } from 'knex';
6
+ import { PermissionResourceRef, PermissionRule, PermissionRuleset } from '@backstage/plugin-permission-node';
7
+ import { Config } from '@backstage/config';
8
+ import { Duration } from 'luxon';
9
+ import { Readable } from 'stream';
9
10
  export { isChildPath } from '@backstage/cli-common';
10
11
 
11
12
  /**
12
- * A generic interface for fetching plain data from URLs.
13
- *
14
- * See the {@link https://backstage.io/docs/backend-system/core-services/url-reader | service documentation} for more details.
15
- *
13
+ * low (default): normal usage
14
+ * medium: accessing write endpoints
15
+ * high: non-root permission changes
16
+ * critical: root permission changes
16
17
  * @public
17
18
  */
18
- interface UrlReaderService {
19
- /**
20
- * Reads a single file and return its content.
21
- */
22
- readUrl(url: string, options?: UrlReaderServiceReadUrlOptions): Promise<UrlReaderServiceReadUrlResponse>;
19
+ type AuditorServiceEventSeverityLevel = 'low' | 'medium' | 'high' | 'critical';
20
+ /** @public */
21
+ type AuditorServiceCreateEventOptions = {
23
22
  /**
24
- * Reads a full or partial file tree.
23
+ * Use kebab-case to name audit events (e.g., "user-login", "file-download", "fetch"). Represents a logical group of similar events or operations. For example, "fetch" could be used as an eventId encompassing various fetch methods like "by-id" or "by-location".
24
+ *
25
+ * The `pluginId` already provides plugin/module context, so avoid redundant prefixes in the `eventId`.
25
26
  */
26
- readTree(url: string, options?: UrlReaderServiceReadTreeOptions): Promise<UrlReaderServiceReadTreeResponse>;
27
+ eventId: string;
28
+ /** (Optional) The severity level for the audit event. */
29
+ severityLevel?: AuditorServiceEventSeverityLevel;
30
+ /** (Optional) The associated HTTP request, if applicable. */
31
+ request?: Request<any, any, any, any, any>;
27
32
  /**
28
- * Searches for a file in a tree using a glob pattern.
33
+ * (Optional) Additional metadata relevant to the event, structured as a JSON object.
34
+ * This could include a `queryType` field, using kebab-case, for variations within the main event (e.g., "by-id", "by-user").
35
+ * For example, if the `eventId` is "fetch", the `queryType` in `meta` could be "by-id" or "by-location".
29
36
  */
30
- search(url: string, options?: UrlReaderServiceSearchOptions): Promise<UrlReaderServiceSearchResponse>;
37
+ meta?: JsonObject;
38
+ };
39
+ /** @public */
40
+ type AuditorServiceEvent = {
41
+ success(options?: {
42
+ meta?: JsonObject;
43
+ }): Promise<void>;
44
+ fail(options: {
45
+ meta?: JsonObject;
46
+ error: Error;
47
+ }): Promise<void>;
48
+ };
49
+ /**
50
+ * A service that provides an auditor facility.
51
+ *
52
+ * See the {@link https://backstage.io/docs/backend-system/core-services/auditor | service documentation} for more details.
53
+ *
54
+ * @public
55
+ */
56
+ interface AuditorService {
57
+ createEvent(options: AuditorServiceCreateEventOptions): Promise<AuditorServiceEvent>;
31
58
  }
59
+
32
60
  /**
33
- * An options object for readUrl operations.
61
+ * Represents a user principal (for example when a user Backstage token issued
62
+ * by the auth backend was given to a request).
63
+ *
64
+ * @remarks
65
+ *
66
+ * Additional information about the user can be fetched using the
67
+ * {@link UserInfoService}.
34
68
  *
35
69
  * @public
36
70
  */
37
- type UrlReaderServiceReadUrlOptions = {
38
- /**
39
- * An ETag which can be provided to check whether a
40
- * {@link UrlReaderService.readUrl} response has changed from a previous execution.
41
- *
42
- * @remarks
43
- *
44
- * In the {@link UrlReaderService.readUrl} response, an ETag is returned along with
45
- * the data. The ETag is a unique identifier of the data, usually the commit
46
- * SHA or ETag from the target.
47
- *
48
- * When an ETag is given in ReadUrlOptions, {@link UrlReaderService.readUrl} will
49
- * first compare the ETag against the ETag of the target. If they match,
50
- * {@link UrlReaderService.readUrl} will throw a
51
- * {@link @backstage/errors#NotModifiedError} indicating that the response
52
- * will not differ from the previous response which included this particular
53
- * ETag. If they do not match, {@link UrlReaderService.readUrl} will return the rest
54
- * of the response along with a new ETag.
55
- */
56
- etag?: string;
57
- /**
58
- * A date which can be provided to check whether a
59
- * {@link UrlReaderService.readUrl} response has changed since the lastModifiedAt.
60
- *
61
- * @remarks
62
- *
63
- * In the {@link UrlReaderService.readUrl} response, an lastModifiedAt is returned
64
- * along with data. The lastModifiedAt date represents the last time the data
65
- * was modified.
66
- *
67
- * When an lastModifiedAfter is given in ReadUrlOptions, {@link UrlReaderService.readUrl}
68
- * will compare the lastModifiedAfter against the lastModifiedAt of the target. If
69
- * the data has not been modified since this date, the {@link UrlReaderService.readUrl}
70
- * will throw a {@link @backstage/errors#NotModifiedError} indicating that the
71
- * response does not contain any new data. If they do not match,
72
- * {@link UrlReaderService.readUrl} will return the rest of the response along with new
73
- * lastModifiedAt date.
74
- */
75
- lastModifiedAfter?: Date;
76
- /**
77
- * An abort signal to pass down to the underlying request.
78
- *
79
- * @remarks
80
- *
81
- * Not all reader implementations may take this field into account.
82
- */
83
- signal?: AbortSignal;
71
+ type BackstageUserPrincipal = {
72
+ type: 'user';
84
73
  /**
85
- * An optional token to use for authentication when reading the resources.
86
- *
87
- * @remarks
88
- *
89
- * By default all URL Readers will use the integrations config which is supplied
90
- * when creating the Readers. Sometimes it might be desireable to use the already
91
- * created URLReaders but with a different token, maybe that's supplied by the user
92
- * at runtime.
74
+ * The entity ref of the user entity that this principal represents.
93
75
  */
94
- token?: string;
76
+ userEntityRef: string;
95
77
  };
96
78
  /**
97
- * A response object for {@link UrlReaderService.readUrl} operations.
79
+ * Represents a principal that is not authenticated (for example when no token
80
+ * at all was given to a request).
98
81
  *
99
82
  * @public
100
83
  */
101
- type UrlReaderServiceReadUrlResponse = {
102
- /**
103
- * Returns the data that was read from the remote URL.
104
- */
105
- buffer(): Promise<Buffer>;
84
+ type BackstageNonePrincipal = {
85
+ type: 'none';
86
+ };
87
+ /**
88
+ * Represents a service principal (for example when an external access method
89
+ * token was given to a request, or the caller was a Backstage backend plugin).
90
+ * @public
91
+ */
92
+ type BackstageServicePrincipal = {
93
+ type: 'service';
106
94
  /**
107
- * Returns the data that was read from the remote URL as a Readable stream.
95
+ * A string that represents the service.
108
96
  *
109
97
  * @remarks
110
98
  *
111
- * This method will be required in a future release.
99
+ * This string is only informational, has no well defined semantics, and
100
+ * should never be used to drive actual logic in code.
112
101
  */
113
- stream?(): Readable;
102
+ subject: string;
114
103
  /**
115
- * Etag returned by content provider.
104
+ * The access restrictions that apply to this principal.
116
105
  *
117
106
  * @remarks
118
107
  *
119
- * Can be used to compare and cache responses when doing subsequent calls.
120
- */
121
- etag?: string;
122
- /**
123
- * Last modified date of the file contents.
108
+ * If no access restrictions are provided the principal is assumed to have
109
+ * unlimited access, at a framework level. The permissions system and
110
+ * individual plugins may or may not still apply additional access controls on
111
+ * top of this.
124
112
  */
125
- lastModifiedAt?: Date;
113
+ accessRestrictions?: BackstagePrincipalAccessRestrictions;
126
114
  };
127
115
  /**
128
- * An options object for {@link UrlReaderService.readTree} operations.
116
+ * The access restrictions that apply to a given principal.
129
117
  *
130
118
  * @public
131
119
  */
132
- type UrlReaderServiceReadTreeOptions = {
120
+ type BackstagePrincipalAccessRestrictions = {
133
121
  /**
134
- * A filter that can be used to select which files should be included.
135
- *
136
- * @remarks
137
- *
138
- * The path passed to the filter function is the relative path from the URL
139
- * that the file tree is fetched from, without any leading '/'.
122
+ * If given, the principal is limited to only performing actions with these
123
+ * named permissions.
140
124
  *
141
- * For example, given the URL https://github.com/my/repo/tree/master/my-dir, a file
142
- * at https://github.com/my/repo/blob/master/my-dir/my-subdir/my-file.txt will
143
- * be represented as my-subdir/my-file.txt
125
+ * Note that this only applies where permissions checks are enabled in the
126
+ * first place. Endpoints that are not protected by the permissions system at
127
+ * all, are not affected by this setting.
144
128
  *
145
- * If no filter is provided, all files are extracted.
129
+ * This array always has at least one element, or is missing entirely.
146
130
  */
147
- filter?(path: string, info?: {
148
- size: number;
149
- }): boolean;
131
+ permissionNames?: string[];
150
132
  /**
151
- * An ETag which can be provided to check whether a
152
- * {@link UrlReaderService.readTree} response has changed from a previous execution.
153
- *
154
- * @remarks
133
+ * If given, the principal is limited to only performing actions whose
134
+ * permissions have these attributes.
155
135
  *
156
- * In the {@link UrlReaderService.readTree} response, an ETag is returned along with
157
- * the tree blob. The ETag is a unique identifier of the tree blob, usually
158
- * the commit SHA or ETag from the target.
136
+ * Note that this only applies where permissions checks are enabled in the
137
+ * first place. Endpoints that are not protected by the permissions system at
138
+ * all, are not affected by this setting.
159
139
  *
160
- * When an ETag is given as a request option, {@link UrlReaderService.readTree} will
161
- * first compare the ETag against the ETag on the target branch. If they
162
- * match, {@link UrlReaderService.readTree} will throw a
163
- * {@link @backstage/errors#NotModifiedError} indicating that the response
164
- * will not differ from the previous response which included this particular
165
- * ETag. If they do not match, {@link UrlReaderService.readTree} will return the
166
- * rest of the response along with a new ETag.
140
+ * This object always has at least one key, or is missing entirely.
167
141
  */
168
- etag?: string;
142
+ permissionAttributes?: {
143
+ /**
144
+ * Match any of these action values. This array always has at least one
145
+ * element, or is missing entirely.
146
+ */
147
+ action?: Array<Required<PermissionAttributes>['action']>;
148
+ };
149
+ };
150
+ /**
151
+ * An opaque representation of credentials, for example as passed in a
152
+ * request-response flow.
153
+ *
154
+ * @public
155
+ */
156
+ type BackstageCredentials<TPrincipal = unknown> = {
157
+ $$type: '@backstage/BackstageCredentials';
169
158
  /**
170
- * An abort signal to pass down to the underlying request.
171
- *
172
- * @remarks
173
- *
174
- * Not all reader implementations may take this field into account.
159
+ * If the credentials have a limited lifetime, this is the time at which they
160
+ * expire and may no longer be accepted by a receiver.
175
161
  */
176
- signal?: AbortSignal;
162
+ expiresAt?: Date;
177
163
  /**
178
- * An optional token to use for authentication when reading the resources.
164
+ * The principal (originator) of the request.
179
165
  *
180
166
  * @remarks
181
167
  *
182
- * By default all URL Readers will use the integrations config which is supplied
183
- * when creating the Readers. Sometimes it might be desireable to use the already
184
- * created URLReaders but with a different token, maybe that's supplied by the user
185
- * at runtime.
168
+ * This is semantically the originator of a request chain, and may or may not
169
+ * represent the immediate caller of your service. For example, in
170
+ * on-behalf-of scenarios, the immediate caller may be an intermediary backend
171
+ * service, but the principal may still be a user that was the original
172
+ * caller.
186
173
  */
187
- token?: string;
174
+ principal: TPrincipal;
188
175
  };
189
176
  /**
190
- * Options that control {@link UrlReaderServiceReadTreeResponse.dir} execution.
177
+ * The types of principal that can be represented in a
178
+ * {@link BackstageCredentials} object.
191
179
  *
192
180
  * @public
193
181
  */
194
- type UrlReaderServiceReadTreeResponseDirOptions = {
195
- /**
196
- * The directory to write files to.
197
- *
198
- * @remarks
199
- *
200
- * Defaults to the OS tmpdir, or `backend.workingDirectory` if set in config.
201
- */
202
- targetDir?: string;
182
+ type BackstagePrincipalTypes = {
183
+ user: BackstageUserPrincipal;
184
+ service: BackstageServicePrincipal;
185
+ none: BackstageNonePrincipal;
186
+ unknown: unknown;
203
187
  };
204
188
  /**
205
- * A response object for {@link UrlReaderService.readTree} operations.
189
+ * Provides token authentication and credentials management.
190
+ *
191
+ * See the {@link https://backstage.io/docs/backend-system/core-services/auth | service documentation} for more details.
206
192
  *
207
193
  * @public
208
194
  */
209
- type UrlReaderServiceReadTreeResponse = {
195
+ interface AuthService {
210
196
  /**
211
- * Returns an array of all the files inside the tree, and corresponding
212
- * functions to read their content.
197
+ * Verifies a token and returns the associated credentials.
213
198
  */
214
- files(): Promise<UrlReaderServiceReadTreeResponseFile[]>;
199
+ authenticate(token: string, options?: {
200
+ /**
201
+ * If set to true, allow limited access tokens (such as cookies).
202
+ *
203
+ * If this flag is not set, or is set to false, calls with limited access
204
+ * tokens will lead to a {@link @backstage/errors#NotAllowedError} being
205
+ * thrown.
206
+ */
207
+ allowLimitedAccess?: boolean;
208
+ }): Promise<BackstageCredentials>;
215
209
  /**
216
- * Returns the tree contents as a binary archive, using a stream.
210
+ * Checks if the given credentials are of the given type, and narrows the
211
+ * TypeScript type accordingly if there's a match.
217
212
  */
218
- archive(): Promise<NodeJS.ReadableStream>;
213
+ isPrincipal<TType extends keyof BackstagePrincipalTypes>(credentials: BackstageCredentials, type: TType): credentials is BackstageCredentials<BackstagePrincipalTypes[TType]>;
219
214
  /**
220
- * Extracts the tree response into a directory and returns the path of the
221
- * directory.
222
- *
223
- * **NOTE**: It is the responsibility of the caller to remove the directory after use.
215
+ * Create a credentials object that represents an unauthenticated caller.
224
216
  */
225
- dir(options?: UrlReaderServiceReadTreeResponseDirOptions): Promise<string>;
217
+ getNoneCredentials(): Promise<BackstageCredentials<BackstageNonePrincipal>>;
226
218
  /**
227
- * Etag returned by content provider.
219
+ * Create a credentials object that represents the current service itself.
220
+ */
221
+ getOwnServiceCredentials(): Promise<BackstageCredentials<BackstageServicePrincipal>>;
222
+ /**
223
+ * Issue a token that can be used for authenticating calls towards other
224
+ * backend plugins.
228
225
  *
229
226
  * @remarks
230
227
  *
231
- * Can be used to compare and cache responses when doing subsequent calls.
228
+ * This method should be called before each request. Do not hold on to the
229
+ * issued token and reuse it for future calls.
232
230
  */
233
- etag: string;
234
- };
235
- /**
236
- * Represents a single file in a {@link UrlReaderService.readTree} response.
237
- *
238
- * @public
239
- */
240
- type UrlReaderServiceReadTreeResponseFile = {
231
+ getPluginRequestToken(options: {
232
+ /**
233
+ * The credentials of the originator of the request.
234
+ *
235
+ * @remarks
236
+ *
237
+ * This is most commonly the result of
238
+ * {@link AuthService.getOwnServiceCredentials} when the current service is
239
+ * the originator, or the output of {@link HttpAuthService.credentials} when
240
+ * performing requests on behalf of an incoming request identity.
241
+ */
242
+ onBehalfOf: BackstageCredentials;
243
+ /**
244
+ * The ID of the plugin that the request is being made to.
245
+ */
246
+ targetPluginId: string;
247
+ }): Promise<{
248
+ token: string;
249
+ }>;
241
250
  /**
242
- * The filepath of the data.
251
+ * Issue a limited user token that can be used e.g. in cookie flows.
243
252
  */
244
- path: string;
253
+ getLimitedUserToken(
245
254
  /**
246
- * The binary contents of the file.
255
+ * The credentials that this token should represent. Must be a user
256
+ * principal. Commonly the output of {@link HttpAuthService.credentials} is
257
+ * used as the input.
247
258
  */
248
- content(): Promise<Buffer>;
259
+ credentials: BackstageCredentials<BackstageUserPrincipal>): Promise<{
260
+ token: string;
261
+ expiresAt: Date;
262
+ }>;
249
263
  /**
250
- * The last modified timestamp of the data.
264
+ * Retrieve the public keys that have been used to sign tokens that were
265
+ * issued by this service. This list is periodically pruned from keys that are
266
+ * significantly past their expiry.
251
267
  */
252
- lastModifiedAt?: Date;
253
- };
268
+ listPublicServiceKeys(): Promise<{
269
+ keys: JsonObject[];
270
+ }>;
271
+ }
272
+
254
273
  /**
255
- * An options object for search operations.
274
+ * Options passed to {@link CacheService.set}.
256
275
  *
257
276
  * @public
258
277
  */
259
- type UrlReaderServiceSearchOptions = {
260
- /**
261
- * An etag can be provided to check whether the search response has changed from a previous execution.
262
- *
263
- * In the search() response, an etag is returned along with the files. The etag is a unique identifier
264
- * of the current tree, usually the commit SHA or etag from the target.
265
- *
266
- * When an etag is given in SearchOptions, search will first compare the etag against the etag
267
- * on the target branch. If they match, search will throw a NotModifiedError indicating that the search
268
- * response will not differ from the previous response which included this particular etag. If they mismatch,
269
- * search will return the rest of SearchResponse along with a new etag.
270
- */
271
- etag?: string;
272
- /**
273
- * An abort signal to pass down to the underlying request.
274
- *
275
- * @remarks
276
- *
277
- * Not all reader implementations may take this field into account.
278
- */
279
- signal?: AbortSignal;
278
+ type CacheServiceSetOptions = {
280
279
  /**
281
- * An optional token to use for authentication when reading the resources.
282
- *
283
- * @remarks
284
- *
285
- * By default all URL Readers will use the integrations config which is supplied
286
- * when creating the Readers. Sometimes it might be desireable to use the already
287
- * created URLReaders but with a different token, maybe that's supplied by the user
288
- * at runtime.
280
+ * Optional TTL (in milliseconds if given as a number). Defaults to the TTL provided when the client
281
+ * was set up (or no TTL if none are provided).
289
282
  */
290
- token?: string;
283
+ ttl?: number | HumanDuration;
291
284
  };
292
285
  /**
293
- * The output of a search operation.
286
+ * Options passed to {@link CacheService.withOptions}.
294
287
  *
295
288
  * @public
296
289
  */
297
- type UrlReaderServiceSearchResponse = {
298
- /**
299
- * The files that matched the search query.
300
- */
301
- files: UrlReaderServiceSearchResponseFile[];
290
+ type CacheServiceOptions = {
302
291
  /**
303
- * A unique identifier of the current remote tree, usually the commit SHA or etag from the target.
292
+ * An optional default TTL (in milliseconds if given as a number) to be set when getting a client
293
+ * instance. If not provided, data will persist indefinitely by default (or
294
+ * can be configured per entry at set-time).
304
295
  */
305
- etag: string;
296
+ defaultTtl?: number | HumanDuration;
306
297
  };
307
298
  /**
308
- * Represents a single file in a search response.
299
+ * A pre-configured, storage agnostic cache service suitable for use by
300
+ * Backstage plugins.
301
+ *
302
+ * See the {@link https://backstage.io/docs/backend-system/core-services/cache | service documentation} for more details.
309
303
  *
310
304
  * @public
311
305
  */
312
- type UrlReaderServiceSearchResponseFile = {
306
+ interface CacheService {
313
307
  /**
314
- * The full URL to the file.
308
+ * Reads data from a cache store for the given key. If no data was found,
309
+ * returns undefined.
315
310
  */
316
- url: string;
311
+ get<TValue extends JsonValue>(key: string): Promise<TValue | undefined>;
317
312
  /**
318
- * The binary contents of the file.
313
+ * Writes the given data to a cache store, associated with the given key. An
314
+ * optional TTL may also be provided, otherwise it defaults to the TTL that
315
+ * was provided when the client was instantiated.
319
316
  */
320
- content(): Promise<Buffer>;
317
+ set(key: string, value: JsonValue, options?: CacheServiceSetOptions): Promise<void>;
321
318
  /**
322
- * The last modified timestamp of the data.
319
+ * Removes the given key from the cache store.
323
320
  */
324
- lastModifiedAt?: Date;
325
- };
321
+ delete(key: string): Promise<void>;
322
+ /**
323
+ * Creates a new {@link CacheService} instance with the given options.
324
+ */
325
+ withOptions(options: CacheServiceOptions): CacheService;
326
+ }
326
327
 
327
328
  /**
328
- * A function that can be called as a scheduled task.
329
+ * Manages access to databases that plugins get.
329
330
  *
330
- * It may optionally accept an abort signal argument. When the signal triggers,
331
- * processing should abort and return as quickly as possible.
331
+ * See the {@link https://backstage.io/docs/backend-system/core-services/database | service documentation} for more details.
332
332
  *
333
333
  * @public
334
334
  */
335
- type SchedulerServiceTaskFunction = ((abortSignal: AbortSignal) => void | Promise<void>) | (() => void | Promise<void>);
335
+ interface DatabaseService {
336
+ /**
337
+ * getClient provides backend plugins database connections for itself.
338
+ *
339
+ * The purpose of this method is to allow plugins to get isolated data
340
+ * stores so that plugins are discouraged from database integration.
341
+ */
342
+ getClient(): Promise<Knex>;
343
+ /**
344
+ * This property is used to control the behavior of database migrations.
345
+ */
346
+ migrations?: {
347
+ /**
348
+ * skip database migrations. Useful if connecting to a read-only database.
349
+ *
350
+ * @defaultValue false
351
+ */
352
+ skip?: boolean;
353
+ };
354
+ }
355
+
336
356
  /**
337
- * A semi-opaque type to describe an actively scheduled task.
357
+ * The DiscoveryService is used to provide a mechanism for backend
358
+ * plugins to discover the endpoints for itself or other backend plugins.
359
+ *
360
+ * See the {@link https://backstage.io/docs/backend-system/core-services/discovery | service documentation} for more details.
361
+ *
362
+ * @remarks
363
+ *
364
+ * The purpose of the discovery API is to allow for many different deployment
365
+ * setups and routing methods through a central configuration, instead
366
+ * of letting each individual plugin manage that configuration.
367
+ *
368
+ * Implementations of the discovery API can be as simple as a URL pattern
369
+ * using the pluginId, but could also have overrides for individual plugins,
370
+ * or query a separate discovery service.
338
371
  *
339
372
  * @public
340
373
  */
341
- type SchedulerServiceTaskDescriptor = {
342
- /**
343
- * The unique identifier of the task.
344
- */
345
- id: string;
374
+ interface DiscoveryService {
346
375
  /**
347
- * The scope of the task.
376
+ * Returns the internal HTTP base URL for a given plugin, without a trailing slash.
377
+ *
378
+ * @remarks
379
+ *
380
+ * The returned URL should point to an internal endpoint for the plugin, with
381
+ * the shortest route possible. The URL should be used for service-to-service
382
+ * communication within a Backstage backend deployment.
383
+ *
384
+ * This method must always be called just before making each request, as opposed to
385
+ * fetching the URL once when constructing an API client. That is to ensure that more
386
+ * flexible routing patterns can be supported where a different result might be returned each time.
387
+ *
388
+ * For example, asking for the URL for `catalog` may return something
389
+ * like `http://10.1.2.3/api/catalog`
348
390
  */
349
- scope: 'global' | 'local';
391
+ getBaseUrl(pluginId: string): Promise<string>;
350
392
  /**
351
- * The settings that control the task flow. This is a semi-opaque structure
352
- * that is mainly there for debugging purposes. Do not make any assumptions
353
- * about the contents of this field.
393
+ * Returns the external HTTP base backend URL for a given plugin, without a trailing slash.
394
+ *
395
+ * @remarks
396
+ *
397
+ * The returned URL should point to an external endpoint for the plugin, such that
398
+ * it is reachable from the Backstage frontend and other external services. The returned
399
+ * URL should be usable for example as a callback / webhook URL.
400
+ *
401
+ * The returned URL should be stable and in general not change unless other static
402
+ * or external configuration is changed. Changes should not come as a surprise
403
+ * to an operator of the Backstage backend.
404
+ *
405
+ * For example, asking for the URL for `catalog` may return something
406
+ * like `https://backstage.example.com/api/catalog`
354
407
  */
355
- settings: {
356
- version: number;
357
- } & JsonObject;
358
- };
408
+ getExternalBaseUrl(pluginId: string): Promise<string>;
409
+ }
410
+
359
411
  /**
360
- * Options that control the scheduling of a task.
412
+ * Provides handling of credentials in an ongoing request.
413
+ *
414
+ * See the {@link https://backstage.io/docs/backend-system/core-services/http-auth | service documentation} for more details.
361
415
  *
362
416
  * @public
363
417
  */
364
- interface SchedulerServiceTaskScheduleDefinition {
418
+ interface HttpAuthService {
365
419
  /**
366
- * How often you want the task to run. The system does its best to avoid
367
- * overlapping invocations.
420
+ * Extracts the caller's credentials from a request.
368
421
  *
369
422
  * @remarks
370
423
  *
371
- * This is the best effort value; under some circumstances there can be
372
- * deviations. For example, if the task runtime is longer than the frequency
373
- * and the timeout has not been given or not been exceeded yet, the next
374
- * invocation of this task will be delayed until after the previous one
375
- * finishes.
376
- *
377
- * This is a required field.
378
- */
379
- frequency: {
380
- /**
381
- * A crontab style string.
382
- *
383
- * @remarks
384
- *
385
- * Overview:
386
- *
387
- * ```
388
- * ┌────────────── second (optional)
389
- * │ ┌──────────── minute
390
- * │ │ ┌────────── hour
391
- * │ │ │ ┌──────── day of month
392
- * │ │ │ │ ┌────── month
393
- * │ │ │ │ │ ┌──── day of week
394
- * │ │ │ │ │ │
395
- * │ │ │ │ │ │
396
- * * * * * * *
397
- * ```
398
- */
399
- cron: string;
400
- } | Duration | HumanDuration | {
401
- trigger: 'manual';
402
- };
403
- /**
404
- * The maximum amount of time that a single task invocation can take, before
405
- * it's considered timed out and gets "released" such that a new invocation
406
- * is permitted to take place (possibly, then, on a different worker).
407
- */
408
- timeout: Duration | HumanDuration;
409
- /**
410
- * The amount of time that should pass before the first invocation happens.
411
- *
412
- * @remarks
424
+ * The credentials have been validated before returning, and are guaranteed to
425
+ * adhere to whatever policies have been added to this route using
426
+ * {@link HttpRouterService.addAuthPolicy}, if any.
413
427
  *
414
- * This can be useful in cold start scenarios to stagger or delay some heavy
415
- * compute jobs. If no value is given for this field then the first invocation
416
- * will happen as soon as possible according to the cadence.
428
+ * Further restrictions can be imposed by passing in options that control the
429
+ * allowed types of credential.
417
430
  *
418
- * NOTE: This is a per-worker delay. If you have a cluster of workers all
419
- * collaborating on a task that has its `scope` field set to `'global'`, then
420
- * you may still see the task being processed by other long-lived workers,
421
- * while any given single worker is in its initial sleep delay time e.g. after
422
- * a deployment. Therefore, this parameter is not useful for "globally" pausing
423
- * work; its main intended use is for individual machines to get a chance to
424
- * reach some equilibrium at startup before triggering heavy batch workloads.
431
+ * You can narrow the returned credentials object to specific principal types
432
+ * using {@link AuthService.isPrincipal}.
425
433
  */
426
- initialDelay?: Duration | HumanDuration;
434
+ credentials<TAllowed extends keyof BackstagePrincipalTypes = 'unknown'>(
427
435
  /**
428
- * Sets the scope of concurrency control / locking to apply for invocations of
429
- * this task.
430
- *
431
- * @remarks
432
- *
433
- * When the scope is set to the default value `'global'`, the scheduler will
434
- * attempt to ensure that only one worker machine runs the task at a time,
435
- * according to the given cadence. This means that as the number of worker
436
- * hosts increases, the invocation frequency of this task will not go up.
437
- * Instead, the load is spread randomly across hosts. This setting is useful
438
- * for tasks that access shared resources, for example catalog ingestion tasks
439
- * where you do not want many machines to repeatedly import the same data and
440
- * trample over each other.
441
- *
442
- * When the scope is set to `'local'`, there is no concurrency control across
443
- * hosts. Each host runs the task according to the given cadence similarly to
444
- * `setInterval`, but the runtime ensures that there are no overlapping runs.
445
- *
446
- * @defaultValue 'global'
436
+ * An Express request object.
447
437
  */
448
- scope?: 'global' | 'local';
449
- }
450
- /**
451
- * Config options for {@link SchedulerServiceTaskScheduleDefinition}
452
- * that control the scheduling of a task.
453
- *
454
- * @public
455
- */
456
- interface SchedulerServiceTaskScheduleDefinitionConfig {
438
+ req: Request<any, any, any, any, any>,
457
439
  /**
458
- * How often you want the task to run. The system does its best to avoid
459
- * overlapping invocations.
460
- *
461
- * @remarks
462
- *
463
- * This is the best effort value; under some circumstances there can be
464
- * deviations. For example, if the task runtime is longer than the frequency
465
- * and the timeout has not been given or not been exceeded yet, the next
466
- * invocation of this task will be delayed until after the previous one
467
- * finishes.
468
- *
469
- * This is a required field.
440
+ * Optional further restrictions.
470
441
  */
471
- frequency: {
442
+ options?: {
472
443
  /**
473
- * A crontab style string.
444
+ * If specified, allow only principals of the given type(s).
474
445
  *
475
- * @remarks
446
+ * If the incoming credentials were not of a type that matched this
447
+ * restriction, a {@link @backstage/errors#NotAllowedError} is thrown.
476
448
  *
477
- * Overview:
449
+ * The default is to allow user and service principals.
450
+ */
451
+ allow?: Array<TAllowed>;
452
+ /**
453
+ * If set to true, allow limited access tokens (such as cookies).
478
454
  *
479
- * ```
480
- * ┌────────────── second (optional)
481
- * ┌──────────── minute
482
- * │ │ ┌────────── hour
483
- * │ │ │ ┌──────── day of month
484
- * │ │ │ │ ┌────── month
485
- * │ │ │ │ │ ┌──── day of week
486
- * │ │ │ │ │ │
487
- * │ │ │ │ │ │
488
- * * * * * * *
489
- * ```
455
+ * If this flag is not set, or is set to false, calls with limited access
456
+ * tokens will lead to a {@link @backstage/errors#NotAllowedError} being
457
+ * thrown.
490
458
  */
491
- cron: string;
492
- } | string | HumanDuration
493
- /**
494
- * This task will only run when manually triggered with the `triggerTask` method; no automatic
495
- * scheduling. This is useful for locking of global tasks that should not be run concurrently.
496
- */
497
- | {
498
- trigger: 'manual';
499
- };
500
- /**
501
- * The maximum amount of time that a single task invocation can take, before
502
- * it's considered timed out and gets "released" such that a new invocation
503
- * is permitted to take place (possibly, then, on a different worker).
504
- */
505
- timeout: string | HumanDuration;
506
- /**
507
- * The amount of time that should pass before the first invocation happens.
508
- *
509
- * @remarks
510
- *
511
- * This can be useful in cold start scenarios to stagger or delay some heavy
512
- * compute jobs. If no value is given for this field then the first invocation
513
- * will happen as soon as possible according to the cadence.
514
- *
515
- * NOTE: This is a per-worker delay. If you have a cluster of workers all
516
- * collaborating on a task that has its `scope` field set to `'global'`, then
517
- * you may still see the task being processed by other long-lived workers,
518
- * while any given single worker is in its initial sleep delay time e.g. after
519
- * a deployment. Therefore, this parameter is not useful for "globally" pausing
520
- * work; its main intended use is for individual machines to get a chance to
521
- * reach some equilibrium at startup before triggering heavy batch workloads.
522
- */
523
- initialDelay?: string | HumanDuration;
459
+ allowLimitedAccess?: boolean;
460
+ }): Promise<BackstageCredentials<BackstagePrincipalTypes[TAllowed]>>;
524
461
  /**
525
- * Sets the scope of concurrency control / locking to apply for invocations of
526
- * this task.
527
- *
528
- * @remarks
529
- *
530
- * When the scope is set to the default value `'global'`, the scheduler will
531
- * attempt to ensure that only one worker machine runs the task at a time,
532
- * according to the given cadence. This means that as the number of worker
533
- * hosts increases, the invocation frequency of this task will not go up.
534
- * Instead, the load is spread randomly across hosts. This setting is useful
535
- * for tasks that access shared resources, for example catalog ingestion tasks
536
- * where you do not want many machines to repeatedly import the same data and
537
- * trample over each other.
538
- *
539
- * When the scope is set to `'local'`, there is no concurrency control across
540
- * hosts. Each host runs the task according to the given cadence similarly to
541
- * `setInterval`, but the runtime ensures that there are no overlapping runs.
462
+ * Issues a limited access token as a cookie on the given response object.
463
+ * This is only possible for requests that were originally made with user
464
+ * credentials (such as a Backstage token).
542
465
  *
543
- * @defaultValue 'global'
544
- */
545
- scope?: 'global' | 'local';
546
- }
547
- /**
548
- * Options that apply to the invocation of a given task.
549
- *
550
- * @public
551
- */
552
- interface SchedulerServiceTaskInvocationDefinition {
553
- /**
554
- * A unique ID (within the scope of the plugin) for the task.
466
+ * This must be called before sending any payload data.
555
467
  */
556
- id: string;
468
+ issueUserCookie(
557
469
  /**
558
- * The actual task function to be invoked regularly.
470
+ * An Express response object.
559
471
  */
560
- fn: SchedulerServiceTaskFunction;
472
+ res: Response,
561
473
  /**
562
- * An abort signal that, when triggered, will stop the recurring execution of
563
- * the task.
474
+ * Optional further settings.
564
475
  */
565
- signal?: AbortSignal;
476
+ options?: {
477
+ /**
478
+ * Issue the cookie for this specific credential. Must be a "user" type
479
+ * principal, or a "none" type (which leads to deleting the cookie).
480
+ *
481
+ * @remarks
482
+ *
483
+ * Normally you do not have to specify this option, because the default
484
+ * behavior is to extract the credentials from the request that
485
+ * corresponded to the given respnse.
486
+ */
487
+ credentials?: BackstageCredentials;
488
+ }): Promise<{
489
+ expiresAt: Date;
490
+ }>;
566
491
  }
492
+
567
493
  /**
568
- * A previously prepared task schedule, ready to be invoked.
494
+ * Options for {@link HttpRouterService.addAuthPolicy}.
569
495
  *
570
496
  * @public
571
497
  */
572
- interface SchedulerServiceTaskRunner {
573
- /**
574
- * Takes the schedule and executes an actual task using it.
575
- *
576
- * @param task - The actual runtime properties of the task
577
- */
578
- run(task: SchedulerServiceTaskInvocationDefinition): Promise<void>;
498
+ interface HttpRouterServiceAuthPolicy {
499
+ path: string;
500
+ allow: 'unauthenticated' | 'user-cookie';
579
501
  }
580
502
  /**
581
- * Deals with the scheduling of distributed tasks, for a given plugin.
503
+ * Allows plugins to register HTTP routes.
582
504
  *
583
- * See the {@link https://backstage.io/docs/backend-system/core-services/scheduler | service documentation} for more details.
505
+ * See the {@link https://backstage.io/docs/backend-system/core-services/http-router | service documentation} for more details.
584
506
  *
585
507
  * @public
586
508
  */
587
- interface SchedulerService {
588
- /**
589
- * Manually triggers a task by ID.
590
- *
591
- * If the task doesn't exist, a NotFoundError is thrown. If the task is
592
- * currently running, a ConflictError is thrown.
593
- *
594
- * @param id - The task ID
595
- */
596
- triggerTask(id: string): Promise<void>;
509
+ interface HttpRouterService {
597
510
  /**
598
- * Schedules a task function for recurring runs.
599
- *
600
- * @remarks
601
- *
602
- * The `scope` task field controls whether to use coordinated exclusive
603
- * invocation across workers, or to just coordinate within the current worker.
604
- *
605
- * This convenience method performs both the scheduling and invocation in one
606
- * go.
607
- *
608
- * @param task - The task definition
511
+ * Registers an Express request handler under the plugin's base router. This
512
+ * typically makes its base path `/api/<plugin-id>`.
609
513
  */
610
- scheduleTask(task: SchedulerServiceTaskScheduleDefinition & SchedulerServiceTaskInvocationDefinition): Promise<void>;
514
+ use(handler: Handler): void;
611
515
  /**
612
- * Creates a scheduled but dormant recurring task, ready to be launched at a
613
- * later time.
516
+ * Adds an auth policy to the router. This is used to allow unauthenticated or
517
+ * cookie based access to parts of a plugin's API.
614
518
  *
615
519
  * @remarks
616
520
  *
617
- * This method is useful for pre-creating a schedule in outer code to be
618
- * passed into an inner implementation, such that the outer code controls
619
- * scheduling while inner code controls implementation.
620
- *
621
- * @param schedule - The task schedule
622
- */
623
- createScheduledTaskRunner(schedule: SchedulerServiceTaskScheduleDefinition): SchedulerServiceTaskRunner;
624
- /**
625
- * Returns all scheduled tasks registered to this scheduler.
521
+ * The paths given follow the same pattern as the routers given to the `use`
522
+ * method, that is, they are relative to the plugin's base URL, and can
523
+ * contain placeholders.
626
524
  *
627
- * @remarks
525
+ * @example
628
526
  *
629
- * This method is useful for triggering tasks manually using the triggerTask
630
- * functionality. Note that the returned tasks contain only tasks that have
631
- * been initialized in this instance of the scheduler.
527
+ * ```ts
528
+ * http.addAuthPolicy({
529
+ * path: '/static/:id',
530
+ * allow: 'user-cookie',
531
+ * });
532
+ * ```
632
533
  *
633
- * @returns Scheduled tasks
534
+ * This allows limited access tokens via cookies on the
535
+ * `/api/<plugin-id>/static/*` paths, but not unauthenticated access.
634
536
  */
635
- getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]>;
537
+ addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void;
636
538
  }
637
- /**
638
- * Reads a {@link SchedulerServiceTaskScheduleDefinition} from config. Expects
639
- * the config not to be the root config, but the config for the definition.
640
- *
641
- * @param config - config for a TaskScheduleDefinition.
642
- * @public
643
- */
644
- declare function readSchedulerServiceTaskScheduleDefinitionFromConfig(config: Config): SchedulerServiceTaskScheduleDefinition;
645
539
 
646
540
  /**
647
541
  * A service that provides a logging facility.
@@ -658,16 +552,6 @@ interface LoggerService {
658
552
  child(meta: JsonObject): LoggerService;
659
553
  }
660
554
 
661
- /**
662
- * Root-level logging.
663
- *
664
- * See the {@link https://backstage.io/docs/backend-system/core-services/root-logger | service documentation} for more details.
665
- *
666
- * @public
667
- */
668
- interface RootLoggerService extends LoggerService {
669
- }
670
-
671
555
  /**
672
556
  * @public
673
557
  */
@@ -719,29 +603,156 @@ interface LifecycleService {
719
603
  }
720
604
 
721
605
  /**
722
- * Registration of backend startup and shutdown lifecycle hooks.
606
+ * Options for {@link PermissionsService} requests.
723
607
  *
724
- * See the {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | service documentation} for more details.
608
+ * @public
609
+ */
610
+ interface PermissionsServiceRequestOptions extends EvaluatorRequestOptions {
611
+ credentials: BackstageCredentials;
612
+ }
613
+ /**
614
+ * Permission system integration for authorization of user/service actions.
615
+ *
616
+ * See the {@link https://backstage.io/docs/permissions/overview | permissions documentation}
617
+ * and the {@link https://backstage.io/docs/backend-system/core-services/permissions | service documentation}
618
+ * for more details.
725
619
  *
726
620
  * @public
727
621
  */
728
- interface RootLifecycleService extends LifecycleService {
729
- addBeforeShutdownHook(hook: () => void | Promise<void>): void;
622
+ interface PermissionsService extends PermissionEvaluator {
623
+ /**
624
+ * Evaluates
625
+ * {@link @backstage/plugin-permission-common#Permission | Permissions} and
626
+ * returns definitive decisions.
627
+ *
628
+ * @remarks
629
+ *
630
+ * The returned array has the same number of items, in the same order, as the
631
+ * given requests.
632
+ */
633
+ authorize(requests: AuthorizePermissionRequest[], options: PermissionsServiceRequestOptions): Promise<AuthorizePermissionResponse[]>;
634
+ /**
635
+ * Evaluates {@link @backstage/plugin-permission-common#ResourcePermission | ResourcePermissions} and returns both definitive and
636
+ * conditional decisions, depending on the configured
637
+ * {@link @backstage/plugin-permission-node#PermissionPolicy}.
638
+ *
639
+ * @remarks
640
+ *
641
+ * This method is useful when the
642
+ * caller needs more control over the processing of conditional decisions. For example, a plugin
643
+ * backend may want to use {@link @backstage/plugin-permission-common#PermissionCriteria | conditions} in a database query instead of
644
+ * evaluating each resource in memory.
645
+ *
646
+ * The returned array has the same number of items, in the same order, as the
647
+ * given requests.
648
+ */
649
+ authorizeConditional(requests: QueryPermissionRequest[], options: PermissionsServiceRequestOptions): Promise<QueryPermissionResponse[]>;
730
650
  }
731
651
 
732
652
  /**
733
- * HTTP route registration for root services.
653
+ * Prevent use of type parameter from contributing to type inference.
734
654
  *
735
- * See the {@link https://backstage.io/docs/backend-system/core-services/root-http-router | service documentation} for more details.
655
+ * https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-980401795
656
+ * @ignore
657
+ */
658
+ type NoInfer<T> = T extends infer S ? S : never;
659
+ /**
660
+ * Options for adding a resource type to the permission system.
736
661
  *
737
662
  * @public
738
663
  */
739
- interface RootHttpRouterService {
664
+ type PermissionsRegistryServiceAddResourceTypeOptions<TResourceType extends string, TResource, TQuery> = {
740
665
  /**
741
- * Registers a handler at the root of the backend router.
742
- * The path is required and may not be empty.
666
+ * The {@link @backstage/plugin-permission-node#PermissionResourceRef} that identifies the resource type.
743
667
  */
744
- use(path: string, handler: Handler): void;
668
+ resourceRef: PermissionResourceRef<TResource, TQuery, TResourceType>;
669
+ /**
670
+ * Permissions that are available for this resource type.
671
+ */
672
+ permissions?: Array<Permission>;
673
+ /**
674
+ * Permission rules that are available for this resource type.
675
+ */
676
+ rules: PermissionRule<NoInfer<TResource>, NoInfer<TQuery>, NoInfer<TResourceType>>[];
677
+ /**
678
+ * The function used to load associated resources based in the provided
679
+ * references.
680
+ *
681
+ * @remarks
682
+ *
683
+ * If this function is not provided the permission system will not be able to
684
+ * resolve conditional decisions except when requesting resources directly
685
+ * from the plugin.
686
+ */
687
+ getResources?(resourceRefs: string[]): Promise<Array<NoInfer<TResource> | undefined>>;
688
+ };
689
+ /**
690
+ * Permission system integration for registering resources and permissions.
691
+ *
692
+ * See the {@link https://backstage.io/docs/permissions/overview | permissions documentation}
693
+ * and the {@link https://backstage.io/docs/backend-system/core-services/permission-integrations | service documentation}
694
+ * for more details.
695
+ *
696
+ * @public
697
+ */
698
+ interface PermissionsRegistryService {
699
+ /**
700
+ * Add permissions for this plugin to the permission system.
701
+ */
702
+ addPermissions(permissions: Permission[]): void;
703
+ /**
704
+ * Adds a set of permission rules to the permission system for a resource type
705
+ * that is owned by this plugin.
706
+ *
707
+ * @remarks
708
+ *
709
+ * Rules should be created using corresponding `create*PermissionRule`
710
+ * functions exported by plugins, who in turn are created with
711
+ * `makeCreatePermissionRule`.
712
+ *
713
+ * Rules can be added either directly by the plugin itself or through a plugin
714
+ * module.
715
+ */
716
+ addPermissionRules(rules: PermissionRule<any, any, string>[]): void;
717
+ /**
718
+ * Add a new resource type that is owned by this plugin to the permission
719
+ * system.
720
+ *
721
+ * @remarks
722
+ *
723
+ * To make this concrete, we can use the Backstage software catalog as an
724
+ * example. The catalog has conditional rules around access to specific
725
+ * _entities_ in the catalog. The _type_ of resource is captured here as
726
+ * `resourceType`, a string identifier (`catalog-entity` in this example) that
727
+ * can be provided with permission definitions. This is merely a _type_ to
728
+ * verify that conditions in an authorization policy are constructed
729
+ * correctly, not a reference to a specific resource.
730
+ *
731
+ * The `rules` parameter is an array of
732
+ * {@link @backstage/plugin-permission-node#PermissionRule}s that introduce
733
+ * conditional filtering logic for resources; for the catalog, these are
734
+ * things like `isEntityOwner` or `hasAnnotation`. Rules describe how to
735
+ * filter a list of resources, and the `conditions` returned allow these rules
736
+ * to be applied with specific parameters (such as 'group:default/team-a', or
737
+ * 'backstage.io/edit-url').
738
+ *
739
+ * The `getResources` argument should load resources based on a reference
740
+ * identifier. For the catalog, this is an
741
+ * [entity reference](https://backstage.io/docs/features/software-catalog/references#string-references).
742
+ * For other plugins, this can be any serialized format. This is used to add a
743
+ * permissions registry API via the HTTP router service. This API will be
744
+ * called by the `permission-backend` when authorization conditions relating
745
+ * to this plugin need to be evaluated.
746
+ */
747
+ addResourceType<const TResourceType extends string, TResource, TQuery>(options: PermissionsRegistryServiceAddResourceTypeOptions<TResourceType, TResource, TQuery>): void;
748
+ /**
749
+ * Returns the set of registered rules for this resource.
750
+ *
751
+ * @remarks
752
+ *
753
+ * Primarily intended for use with {@link @backstage/plugin-permission-node#createConditionAuthorizer} and {@link @backstage/plugin-permission-node#createConditionTransformer}.
754
+ */
755
+ getPermissionRuleset<TResourceType extends string, TResource, TQuery>(resourceRef: PermissionResourceRef<TResource, TQuery, TResourceType>): PermissionRuleset<TResource, TQuery, TResourceType>;
745
756
  }
746
757
 
747
758
  /**
@@ -759,563 +770,707 @@ interface PluginMetadataService {
759
770
  }
760
771
 
761
772
  /**
762
- * Represents a user principal (for example when a user Backstage token issued
763
- * by the auth backend was given to a request).
773
+ * Provides access to static configuration.
764
774
  *
765
- * @remarks
775
+ * See the {@link https://backstage.io/docs/conf/ | configuration documentation}
776
+ * and the {@link https://backstage.io/docs/backend-system/core-services/root-config | service documentation}
777
+ * for more details.
766
778
  *
767
- * Additional information about the user can be fetched using the
768
- * {@link UserInfoService}.
779
+ * @public
780
+ */
781
+ interface RootConfigService extends Config {
782
+ }
783
+
784
+ /**
785
+ * @public
786
+ */
787
+ interface RootHealthService {
788
+ /**
789
+ * Get the liveness status of the backend.
790
+ */
791
+ getLiveness(): Promise<{
792
+ status: number;
793
+ payload?: JsonValue;
794
+ }>;
795
+ /**
796
+ * Get the readiness status of the backend.
797
+ */
798
+ getReadiness(): Promise<{
799
+ status: number;
800
+ payload?: JsonValue;
801
+ }>;
802
+ }
803
+
804
+ /**
805
+ * HTTP route registration for root services.
806
+ *
807
+ * See the {@link https://backstage.io/docs/backend-system/core-services/root-http-router | service documentation} for more details.
769
808
  *
770
809
  * @public
771
810
  */
772
- type BackstageUserPrincipal = {
773
- type: 'user';
811
+ interface RootHttpRouterService {
774
812
  /**
775
- * The entity ref of the user entity that this principal represents.
813
+ * Registers a handler at the root of the backend router.
814
+ * The path is required and may not be empty.
776
815
  */
777
- userEntityRef: string;
778
- };
816
+ use(path: string, handler: Handler): void;
817
+ }
818
+
779
819
  /**
780
- * Represents a principal that is not authenticated (for example when no token
781
- * at all was given to a request).
820
+ * Registration of backend startup and shutdown lifecycle hooks.
821
+ *
822
+ * See the {@link https://backstage.io/docs/backend-system/core-services/root-lifecycle | service documentation} for more details.
782
823
  *
783
824
  * @public
784
825
  */
785
- type BackstageNonePrincipal = {
786
- type: 'none';
826
+ interface RootLifecycleService extends LifecycleService {
827
+ addBeforeShutdownHook(hook: () => void | Promise<void>): void;
828
+ }
829
+
830
+ /**
831
+ * Root-level logging.
832
+ *
833
+ * See the {@link https://backstage.io/docs/backend-system/core-services/root-logger | service documentation} for more details.
834
+ *
835
+ * @public
836
+ */
837
+ interface RootLoggerService extends LoggerService {
838
+ }
839
+
840
+ /**
841
+ * A function that can be called as a scheduled task.
842
+ *
843
+ * It may optionally accept an abort signal argument. When the signal triggers,
844
+ * processing should abort and return as quickly as possible.
845
+ *
846
+ * @public
847
+ */
848
+ type SchedulerServiceTaskFunction = ((abortSignal: AbortSignal) => void | Promise<void>) | (() => void | Promise<void>);
849
+ /**
850
+ * A semi-opaque type to describe an actively scheduled task.
851
+ *
852
+ * @public
853
+ */
854
+ type SchedulerServiceTaskDescriptor = {
855
+ /**
856
+ * The unique identifier of the task.
857
+ */
858
+ id: string;
859
+ /**
860
+ * The scope of the task.
861
+ */
862
+ scope: 'global' | 'local';
863
+ /**
864
+ * The settings that control the task flow. This is a semi-opaque structure
865
+ * that is mainly there for debugging purposes. Do not make any assumptions
866
+ * about the contents of this field.
867
+ */
868
+ settings: {
869
+ version: number;
870
+ } & JsonObject;
787
871
  };
788
872
  /**
789
- * Represents a service principal (for example when an external access method
790
- * token was given to a request, or the caller was a Backstage backend plugin).
873
+ * Options that control the scheduling of a task.
874
+ *
791
875
  * @public
792
876
  */
793
- type BackstageServicePrincipal = {
794
- type: 'service';
877
+ interface SchedulerServiceTaskScheduleDefinition {
795
878
  /**
796
- * A string that represents the service.
879
+ * How often you want the task to run. The system does its best to avoid
880
+ * overlapping invocations.
797
881
  *
798
882
  * @remarks
799
883
  *
800
- * This string is only informational, has no well defined semantics, and
801
- * should never be used to drive actual logic in code.
884
+ * This is the best effort value; under some circumstances there can be
885
+ * deviations. For example, if the task runtime is longer than the frequency
886
+ * and the timeout has not been given or not been exceeded yet, the next
887
+ * invocation of this task will be delayed until after the previous one
888
+ * finishes.
889
+ *
890
+ * This is a required field.
891
+ */
892
+ frequency: {
893
+ /**
894
+ * A crontab style string.
895
+ *
896
+ * @remarks
897
+ *
898
+ * Overview:
899
+ *
900
+ * ```
901
+ * ┌────────────── second (optional)
902
+ * │ ┌──────────── minute
903
+ * │ │ ┌────────── hour
904
+ * │ │ │ ┌──────── day of month
905
+ * │ │ │ │ ┌────── month
906
+ * │ │ │ │ │ ┌──── day of week
907
+ * │ │ │ │ │ │
908
+ * │ │ │ │ │ │
909
+ * * * * * * *
910
+ * ```
911
+ */
912
+ cron: string;
913
+ } | Duration | HumanDuration | {
914
+ trigger: 'manual';
915
+ };
916
+ /**
917
+ * The maximum amount of time that a single task invocation can take, before
918
+ * it's considered timed out and gets "released" such that a new invocation
919
+ * is permitted to take place (possibly, then, on a different worker).
802
920
  */
803
- subject: string;
921
+ timeout: Duration | HumanDuration;
804
922
  /**
805
- * The access restrictions that apply to this principal.
923
+ * The amount of time that should pass before the first invocation happens.
806
924
  *
807
925
  * @remarks
808
926
  *
809
- * If no access restrictions are provided the principal is assumed to have
810
- * unlimited access, at a framework level. The permissions system and
811
- * individual plugins may or may not still apply additional access controls on
812
- * top of this.
927
+ * This can be useful in cold start scenarios to stagger or delay some heavy
928
+ * compute jobs. If no value is given for this field then the first invocation
929
+ * will happen as soon as possible according to the cadence.
930
+ *
931
+ * NOTE: This is a per-worker delay. If you have a cluster of workers all
932
+ * collaborating on a task that has its `scope` field set to `'global'`, then
933
+ * you may still see the task being processed by other long-lived workers,
934
+ * while any given single worker is in its initial sleep delay time e.g. after
935
+ * a deployment. Therefore, this parameter is not useful for "globally" pausing
936
+ * work; its main intended use is for individual machines to get a chance to
937
+ * reach some equilibrium at startup before triggering heavy batch workloads.
813
938
  */
814
- accessRestrictions?: BackstagePrincipalAccessRestrictions;
815
- };
816
- /**
817
- * The access restrictions that apply to a given principal.
818
- *
819
- * @public
820
- */
821
- type BackstagePrincipalAccessRestrictions = {
939
+ initialDelay?: Duration | HumanDuration;
822
940
  /**
823
- * If given, the principal is limited to only performing actions with these
824
- * named permissions.
941
+ * Sets the scope of concurrency control / locking to apply for invocations of
942
+ * this task.
825
943
  *
826
- * Note that this only applies where permissions checks are enabled in the
827
- * first place. Endpoints that are not protected by the permissions system at
828
- * all, are not affected by this setting.
944
+ * @remarks
829
945
  *
830
- * This array always has at least one element, or is missing entirely.
831
- */
832
- permissionNames?: string[];
833
- /**
834
- * If given, the principal is limited to only performing actions whose
835
- * permissions have these attributes.
946
+ * When the scope is set to the default value `'global'`, the scheduler will
947
+ * attempt to ensure that only one worker machine runs the task at a time,
948
+ * according to the given cadence. This means that as the number of worker
949
+ * hosts increases, the invocation frequency of this task will not go up.
950
+ * Instead, the load is spread randomly across hosts. This setting is useful
951
+ * for tasks that access shared resources, for example catalog ingestion tasks
952
+ * where you do not want many machines to repeatedly import the same data and
953
+ * trample over each other.
836
954
  *
837
- * Note that this only applies where permissions checks are enabled in the
838
- * first place. Endpoints that are not protected by the permissions system at
839
- * all, are not affected by this setting.
955
+ * When the scope is set to `'local'`, there is no concurrency control across
956
+ * hosts. Each host runs the task according to the given cadence similarly to
957
+ * `setInterval`, but the runtime ensures that there are no overlapping runs.
840
958
  *
841
- * This object always has at least one key, or is missing entirely.
959
+ * @defaultValue 'global'
842
960
  */
843
- permissionAttributes?: {
844
- /**
845
- * Match any of these action values. This array always has at least one
846
- * element, or is missing entirely.
847
- */
848
- action?: Array<Required<PermissionAttributes>['action']>;
849
- };
850
- };
961
+ scope?: 'global' | 'local';
962
+ }
851
963
  /**
852
- * An opaque representation of credentials, for example as passed in a
853
- * request-response flow.
964
+ * Config options for {@link SchedulerServiceTaskScheduleDefinition}
965
+ * that control the scheduling of a task.
854
966
  *
855
967
  * @public
856
968
  */
857
- type BackstageCredentials<TPrincipal = unknown> = {
858
- $$type: '@backstage/BackstageCredentials';
859
- /**
860
- * If the credentials have a limited lifetime, this is the time at which they
861
- * expire and may no longer be accepted by a receiver.
862
- */
863
- expiresAt?: Date;
969
+ interface SchedulerServiceTaskScheduleDefinitionConfig {
864
970
  /**
865
- * The principal (originator) of the request.
971
+ * How often you want the task to run. The system does its best to avoid
972
+ * overlapping invocations.
866
973
  *
867
974
  * @remarks
868
975
  *
869
- * This is semantically the originator of a request chain, and may or may not
870
- * represent the immediate caller of your service. For example, in
871
- * on-behalf-of scenarios, the immediate caller may be an intermediary backend
872
- * service, but the principal may still be a user that was the original
873
- * caller.
874
- */
875
- principal: TPrincipal;
876
- };
877
- /**
878
- * The types of principal that can be represented in a
879
- * {@link BackstageCredentials} object.
880
- *
881
- * @public
882
- */
883
- type BackstagePrincipalTypes = {
884
- user: BackstageUserPrincipal;
885
- service: BackstageServicePrincipal;
886
- none: BackstageNonePrincipal;
887
- unknown: unknown;
888
- };
889
- /**
890
- * Provides token authentication and credentials management.
891
- *
892
- * See the {@link https://backstage.io/docs/backend-system/core-services/auth | service documentation} for more details.
893
- *
894
- * @public
895
- */
896
- interface AuthService {
897
- /**
898
- * Verifies a token and returns the associated credentials.
976
+ * This is the best effort value; under some circumstances there can be
977
+ * deviations. For example, if the task runtime is longer than the frequency
978
+ * and the timeout has not been given or not been exceeded yet, the next
979
+ * invocation of this task will be delayed until after the previous one
980
+ * finishes.
981
+ *
982
+ * This is a required field.
899
983
  */
900
- authenticate(token: string, options?: {
984
+ frequency: {
901
985
  /**
902
- * If set to true, allow limited access tokens (such as cookies).
986
+ * A crontab style string.
903
987
  *
904
- * If this flag is not set, or is set to false, calls with limited access
905
- * tokens will lead to a {@link @backstage/errors#NotAllowedError} being
906
- * thrown.
988
+ * @remarks
989
+ *
990
+ * Overview:
991
+ *
992
+ * ```
993
+ * ┌────────────── second (optional)
994
+ * │ ┌──────────── minute
995
+ * │ │ ┌────────── hour
996
+ * │ │ │ ┌──────── day of month
997
+ * │ │ │ │ ┌────── month
998
+ * │ │ │ │ │ ┌──── day of week
999
+ * │ │ │ │ │ │
1000
+ * │ │ │ │ │ │
1001
+ * * * * * * *
1002
+ * ```
907
1003
  */
908
- allowLimitedAccess?: boolean;
909
- }): Promise<BackstageCredentials>;
1004
+ cron: string;
1005
+ } | string | HumanDuration
910
1006
  /**
911
- * Checks if the given credentials are of the given type, and narrows the
912
- * TypeScript type accordingly if there's a match.
1007
+ * This task will only run when manually triggered with the `triggerTask` method; no automatic
1008
+ * scheduling. This is useful for locking of global tasks that should not be run concurrently.
913
1009
  */
914
- isPrincipal<TType extends keyof BackstagePrincipalTypes>(credentials: BackstageCredentials, type: TType): credentials is BackstageCredentials<BackstagePrincipalTypes[TType]>;
1010
+ | {
1011
+ trigger: 'manual';
1012
+ };
915
1013
  /**
916
- * Create a credentials object that represents an unauthenticated caller.
1014
+ * The maximum amount of time that a single task invocation can take, before
1015
+ * it's considered timed out and gets "released" such that a new invocation
1016
+ * is permitted to take place (possibly, then, on a different worker).
917
1017
  */
918
- getNoneCredentials(): Promise<BackstageCredentials<BackstageNonePrincipal>>;
1018
+ timeout: string | HumanDuration;
919
1019
  /**
920
- * Create a credentials object that represents the current service itself.
1020
+ * The amount of time that should pass before the first invocation happens.
1021
+ *
1022
+ * @remarks
1023
+ *
1024
+ * This can be useful in cold start scenarios to stagger or delay some heavy
1025
+ * compute jobs. If no value is given for this field then the first invocation
1026
+ * will happen as soon as possible according to the cadence.
1027
+ *
1028
+ * NOTE: This is a per-worker delay. If you have a cluster of workers all
1029
+ * collaborating on a task that has its `scope` field set to `'global'`, then
1030
+ * you may still see the task being processed by other long-lived workers,
1031
+ * while any given single worker is in its initial sleep delay time e.g. after
1032
+ * a deployment. Therefore, this parameter is not useful for "globally" pausing
1033
+ * work; its main intended use is for individual machines to get a chance to
1034
+ * reach some equilibrium at startup before triggering heavy batch workloads.
921
1035
  */
922
- getOwnServiceCredentials(): Promise<BackstageCredentials<BackstageServicePrincipal>>;
1036
+ initialDelay?: string | HumanDuration;
923
1037
  /**
924
- * Issue a token that can be used for authenticating calls towards other
925
- * backend plugins.
1038
+ * Sets the scope of concurrency control / locking to apply for invocations of
1039
+ * this task.
926
1040
  *
927
1041
  * @remarks
928
1042
  *
929
- * This method should be called before each request. Do not hold on to the
930
- * issued token and reuse it for future calls.
1043
+ * When the scope is set to the default value `'global'`, the scheduler will
1044
+ * attempt to ensure that only one worker machine runs the task at a time,
1045
+ * according to the given cadence. This means that as the number of worker
1046
+ * hosts increases, the invocation frequency of this task will not go up.
1047
+ * Instead, the load is spread randomly across hosts. This setting is useful
1048
+ * for tasks that access shared resources, for example catalog ingestion tasks
1049
+ * where you do not want many machines to repeatedly import the same data and
1050
+ * trample over each other.
1051
+ *
1052
+ * When the scope is set to `'local'`, there is no concurrency control across
1053
+ * hosts. Each host runs the task according to the given cadence similarly to
1054
+ * `setInterval`, but the runtime ensures that there are no overlapping runs.
1055
+ *
1056
+ * @defaultValue 'global'
931
1057
  */
932
- getPluginRequestToken(options: {
933
- /**
934
- * The credentials of the originator of the request.
935
- *
936
- * @remarks
937
- *
938
- * This is most commonly the result of
939
- * {@link AuthService.getOwnServiceCredentials} when the current service is
940
- * the originator, or the output of {@link HttpAuthService.credentials} when
941
- * performing requests on behalf of an incoming request identity.
942
- */
943
- onBehalfOf: BackstageCredentials;
944
- /**
945
- * The ID of the plugin that the request is being made to.
946
- */
947
- targetPluginId: string;
948
- }): Promise<{
949
- token: string;
950
- }>;
1058
+ scope?: 'global' | 'local';
1059
+ }
1060
+ /**
1061
+ * Options that apply to the invocation of a given task.
1062
+ *
1063
+ * @public
1064
+ */
1065
+ interface SchedulerServiceTaskInvocationDefinition {
951
1066
  /**
952
- * Issue a limited user token that can be used e.g. in cookie flows.
1067
+ * A unique ID (within the scope of the plugin) for the task.
953
1068
  */
954
- getLimitedUserToken(
1069
+ id: string;
955
1070
  /**
956
- * The credentials that this token should represent. Must be a user
957
- * principal. Commonly the output of {@link HttpAuthService.credentials} is
958
- * used as the input.
1071
+ * The actual task function to be invoked regularly.
959
1072
  */
960
- credentials: BackstageCredentials<BackstageUserPrincipal>): Promise<{
961
- token: string;
962
- expiresAt: Date;
963
- }>;
1073
+ fn: SchedulerServiceTaskFunction;
964
1074
  /**
965
- * Retrieve the public keys that have been used to sign tokens that were
966
- * issued by this service. This list is periodically pruned from keys that are
967
- * significantly past their expiry.
1075
+ * An abort signal that, when triggered, will stop the recurring execution of
1076
+ * the task.
968
1077
  */
969
- listPublicServiceKeys(): Promise<{
970
- keys: JsonObject[];
971
- }>;
1078
+ signal?: AbortSignal;
972
1079
  }
973
-
974
1080
  /**
975
- * Options for {@link PermissionsService} requests.
1081
+ * A previously prepared task schedule, ready to be invoked.
976
1082
  *
977
1083
  * @public
978
1084
  */
979
- interface PermissionsServiceRequestOptions extends EvaluatorRequestOptions {
980
- credentials: BackstageCredentials;
1085
+ interface SchedulerServiceTaskRunner {
1086
+ /**
1087
+ * Takes the schedule and executes an actual task using it.
1088
+ *
1089
+ * @param task - The actual runtime properties of the task
1090
+ */
1091
+ run(task: SchedulerServiceTaskInvocationDefinition): Promise<void>;
981
1092
  }
982
1093
  /**
983
- * Permission system integration for authorization of user/service actions.
1094
+ * Deals with the scheduling of distributed tasks, for a given plugin.
984
1095
  *
985
- * See the {@link https://backstage.io/docs/permissions/overview | permissions documentation}
986
- * and the {@link https://backstage.io/docs/backend-system/core-services/permissions | service documentation}
987
- * for more details.
1096
+ * See the {@link https://backstage.io/docs/backend-system/core-services/scheduler | service documentation} for more details.
988
1097
  *
989
1098
  * @public
990
1099
  */
991
- interface PermissionsService extends PermissionEvaluator {
1100
+ interface SchedulerService {
992
1101
  /**
993
- * Evaluates
994
- * {@link @backstage/plugin-permission-common#Permission | Permissions} and
995
- * returns definitive decisions.
1102
+ * Manually triggers a task by ID.
1103
+ *
1104
+ * If the task doesn't exist, a NotFoundError is thrown. If the task is
1105
+ * currently running, a ConflictError is thrown.
1106
+ *
1107
+ * @param id - The task ID
1108
+ */
1109
+ triggerTask(id: string): Promise<void>;
1110
+ /**
1111
+ * Schedules a task function for recurring runs.
996
1112
  *
997
1113
  * @remarks
998
1114
  *
999
- * The returned array has the same number of items, in the same order, as the
1000
- * given requests.
1115
+ * The `scope` task field controls whether to use coordinated exclusive
1116
+ * invocation across workers, or to just coordinate within the current worker.
1117
+ *
1118
+ * This convenience method performs both the scheduling and invocation in one
1119
+ * go.
1120
+ *
1121
+ * @param task - The task definition
1001
1122
  */
1002
- authorize(requests: AuthorizePermissionRequest[], options: PermissionsServiceRequestOptions): Promise<AuthorizePermissionResponse[]>;
1123
+ scheduleTask(task: SchedulerServiceTaskScheduleDefinition & SchedulerServiceTaskInvocationDefinition): Promise<void>;
1003
1124
  /**
1004
- * Evaluates {@link @backstage/plugin-permission-common#ResourcePermission | ResourcePermissions} and returns both definitive and
1005
- * conditional decisions, depending on the configured
1006
- * {@link @backstage/plugin-permission-node#PermissionPolicy}.
1125
+ * Creates a scheduled but dormant recurring task, ready to be launched at a
1126
+ * later time.
1007
1127
  *
1008
1128
  * @remarks
1009
1129
  *
1010
- * This method is useful when the
1011
- * caller needs more control over the processing of conditional decisions. For example, a plugin
1012
- * backend may want to use {@link @backstage/plugin-permission-common#PermissionCriteria | conditions} in a database query instead of
1013
- * evaluating each resource in memory.
1130
+ * This method is useful for pre-creating a schedule in outer code to be
1131
+ * passed into an inner implementation, such that the outer code controls
1132
+ * scheduling while inner code controls implementation.
1014
1133
  *
1015
- * The returned array has the same number of items, in the same order, as the
1016
- * given requests.
1134
+ * @param schedule - The task schedule
1017
1135
  */
1018
- authorizeConditional(requests: QueryPermissionRequest[], options: PermissionsServiceRequestOptions): Promise<QueryPermissionResponse[]>;
1136
+ createScheduledTaskRunner(schedule: SchedulerServiceTaskScheduleDefinition): SchedulerServiceTaskRunner;
1137
+ /**
1138
+ * Returns all scheduled tasks registered to this scheduler.
1139
+ *
1140
+ * @remarks
1141
+ *
1142
+ * This method is useful for triggering tasks manually using the triggerTask
1143
+ * functionality. Note that the returned tasks contain only tasks that have
1144
+ * been initialized in this instance of the scheduler.
1145
+ *
1146
+ * @returns Scheduled tasks
1147
+ */
1148
+ getScheduledTasks(): Promise<SchedulerServiceTaskDescriptor[]>;
1019
1149
  }
1020
-
1021
1150
  /**
1022
- * Options for {@link HttpRouterService.addAuthPolicy}.
1151
+ * Reads a {@link SchedulerServiceTaskScheduleDefinition} from config. Expects
1152
+ * the config not to be the root config, but the config for the definition.
1023
1153
  *
1154
+ * @param config - config for a TaskScheduleDefinition.
1024
1155
  * @public
1025
1156
  */
1026
- interface HttpRouterServiceAuthPolicy {
1027
- path: string;
1028
- allow: 'unauthenticated' | 'user-cookie';
1029
- }
1157
+ declare function readSchedulerServiceTaskScheduleDefinitionFromConfig(config: Config): SchedulerServiceTaskScheduleDefinition;
1158
+
1030
1159
  /**
1031
- * Allows plugins to register HTTP routes.
1160
+ * A generic interface for fetching plain data from URLs.
1032
1161
  *
1033
- * See the {@link https://backstage.io/docs/backend-system/core-services/http-router | service documentation} for more details.
1162
+ * See the {@link https://backstage.io/docs/backend-system/core-services/url-reader | service documentation} for more details.
1034
1163
  *
1035
1164
  * @public
1036
1165
  */
1037
- interface HttpRouterService {
1166
+ interface UrlReaderService {
1038
1167
  /**
1039
- * Registers an Express request handler under the plugin's base router. This
1040
- * typically makes its base path `/api/<plugin-id>`.
1168
+ * Reads a single file and return its content.
1041
1169
  */
1042
- use(handler: Handler): void;
1170
+ readUrl(url: string, options?: UrlReaderServiceReadUrlOptions): Promise<UrlReaderServiceReadUrlResponse>;
1043
1171
  /**
1044
- * Adds an auth policy to the router. This is used to allow unauthenticated or
1045
- * cookie based access to parts of a plugin's API.
1046
- *
1047
- * @remarks
1048
- *
1049
- * The paths given follow the same pattern as the routers given to the `use`
1050
- * method, that is, they are relative to the plugin's base URL, and can
1051
- * contain placeholders.
1052
- *
1053
- * @example
1054
- *
1055
- * ```ts
1056
- * http.addAuthPolicy({
1057
- * path: '/static/:id',
1058
- * allow: 'user-cookie',
1059
- * });
1060
- * ```
1061
- *
1062
- * This allows limited access tokens via cookies on the
1063
- * `/api/<plugin-id>/static/*` paths, but not unauthenticated access.
1172
+ * Reads a full or partial file tree.
1064
1173
  */
1065
- addAuthPolicy(policy: HttpRouterServiceAuthPolicy): void;
1174
+ readTree(url: string, options?: UrlReaderServiceReadTreeOptions): Promise<UrlReaderServiceReadTreeResponse>;
1175
+ /**
1176
+ * Searches for a file in a tree using a glob pattern.
1177
+ */
1178
+ search(url: string, options?: UrlReaderServiceSearchOptions): Promise<UrlReaderServiceSearchResponse>;
1066
1179
  }
1067
-
1068
1180
  /**
1069
- * Provides handling of credentials in an ongoing request.
1070
- *
1071
- * See the {@link https://backstage.io/docs/backend-system/core-services/http-auth | service documentation} for more details.
1181
+ * An options object for readUrl operations.
1072
1182
  *
1073
1183
  * @public
1074
1184
  */
1075
- interface HttpAuthService {
1185
+ type UrlReaderServiceReadUrlOptions = {
1076
1186
  /**
1077
- * Extracts the caller's credentials from a request.
1187
+ * An ETag which can be provided to check whether a
1188
+ * {@link UrlReaderService.readUrl} response has changed from a previous execution.
1078
1189
  *
1079
1190
  * @remarks
1080
1191
  *
1081
- * The credentials have been validated before returning, and are guaranteed to
1082
- * adhere to whatever policies have been added to this route using
1083
- * {@link HttpRouterService.addAuthPolicy}, if any.
1084
- *
1085
- * Further restrictions can be imposed by passing in options that control the
1086
- * allowed types of credential.
1192
+ * In the {@link UrlReaderService.readUrl} response, an ETag is returned along with
1193
+ * the data. The ETag is a unique identifier of the data, usually the commit
1194
+ * SHA or ETag from the target.
1087
1195
  *
1088
- * You can narrow the returned credentials object to specific principal types
1089
- * using {@link AuthService.isPrincipal}.
1196
+ * When an ETag is given in ReadUrlOptions, {@link UrlReaderService.readUrl} will
1197
+ * first compare the ETag against the ETag of the target. If they match,
1198
+ * {@link UrlReaderService.readUrl} will throw a
1199
+ * {@link @backstage/errors#NotModifiedError} indicating that the response
1200
+ * will not differ from the previous response which included this particular
1201
+ * ETag. If they do not match, {@link UrlReaderService.readUrl} will return the rest
1202
+ * of the response along with a new ETag.
1090
1203
  */
1091
- credentials<TAllowed extends keyof BackstagePrincipalTypes = 'unknown'>(
1204
+ etag?: string;
1092
1205
  /**
1093
- * An Express request object.
1206
+ * A date which can be provided to check whether a
1207
+ * {@link UrlReaderService.readUrl} response has changed since the lastModifiedAt.
1208
+ *
1209
+ * @remarks
1210
+ *
1211
+ * In the {@link UrlReaderService.readUrl} response, an lastModifiedAt is returned
1212
+ * along with data. The lastModifiedAt date represents the last time the data
1213
+ * was modified.
1214
+ *
1215
+ * When an lastModifiedAfter is given in ReadUrlOptions, {@link UrlReaderService.readUrl}
1216
+ * will compare the lastModifiedAfter against the lastModifiedAt of the target. If
1217
+ * the data has not been modified since this date, the {@link UrlReaderService.readUrl}
1218
+ * will throw a {@link @backstage/errors#NotModifiedError} indicating that the
1219
+ * response does not contain any new data. If they do not match,
1220
+ * {@link UrlReaderService.readUrl} will return the rest of the response along with new
1221
+ * lastModifiedAt date.
1094
1222
  */
1095
- req: Request<any, any, any, any, any>,
1223
+ lastModifiedAfter?: Date;
1096
1224
  /**
1097
- * Optional further restrictions.
1225
+ * An abort signal to pass down to the underlying request.
1226
+ *
1227
+ * @remarks
1228
+ *
1229
+ * Not all reader implementations may take this field into account.
1098
1230
  */
1099
- options?: {
1100
- /**
1101
- * If specified, allow only principals of the given type(s).
1102
- *
1103
- * If the incoming credentials were not of a type that matched this
1104
- * restriction, a {@link @backstage/errors#NotAllowedError} is thrown.
1105
- *
1106
- * The default is to allow user and service principals.
1107
- */
1108
- allow?: Array<TAllowed>;
1109
- /**
1110
- * If set to true, allow limited access tokens (such as cookies).
1111
- *
1112
- * If this flag is not set, or is set to false, calls with limited access
1113
- * tokens will lead to a {@link @backstage/errors#NotAllowedError} being
1114
- * thrown.
1115
- */
1116
- allowLimitedAccess?: boolean;
1117
- }): Promise<BackstageCredentials<BackstagePrincipalTypes[TAllowed]>>;
1231
+ signal?: AbortSignal;
1118
1232
  /**
1119
- * Issues a limited access token as a cookie on the given response object.
1120
- * This is only possible for requests that were originally made with user
1121
- * credentials (such as a Backstage token).
1233
+ * An optional token to use for authentication when reading the resources.
1122
1234
  *
1123
- * This must be called before sending any payload data.
1235
+ * @remarks
1236
+ *
1237
+ * By default all URL Readers will use the integrations config which is supplied
1238
+ * when creating the Readers. Sometimes it might be desireable to use the already
1239
+ * created URLReaders but with a different token, maybe that's supplied by the user
1240
+ * at runtime.
1124
1241
  */
1125
- issueUserCookie(
1242
+ token?: string;
1243
+ };
1244
+ /**
1245
+ * A response object for {@link UrlReaderService.readUrl} operations.
1246
+ *
1247
+ * @public
1248
+ */
1249
+ type UrlReaderServiceReadUrlResponse = {
1126
1250
  /**
1127
- * An Express response object.
1251
+ * Returns the data that was read from the remote URL.
1128
1252
  */
1129
- res: Response,
1253
+ buffer(): Promise<Buffer>;
1130
1254
  /**
1131
- * Optional further settings.
1255
+ * Returns the data that was read from the remote URL as a Readable stream.
1256
+ *
1257
+ * @remarks
1258
+ *
1259
+ * This method will be required in a future release.
1132
1260
  */
1133
- options?: {
1134
- /**
1135
- * Issue the cookie for this specific credential. Must be a "user" type
1136
- * principal, or a "none" type (which leads to deleting the cookie).
1137
- *
1138
- * @remarks
1139
- *
1140
- * Normally you do not have to specify this option, because the default
1141
- * behavior is to extract the credentials from the request that
1142
- * corresponded to the given respnse.
1143
- */
1144
- credentials?: BackstageCredentials;
1145
- }): Promise<{
1146
- expiresAt: Date;
1147
- }>;
1148
- }
1149
-
1150
- /**
1151
- * @public
1152
- */
1153
- interface RootHealthService {
1261
+ stream?(): Readable;
1154
1262
  /**
1155
- * Get the liveness status of the backend.
1263
+ * Etag returned by content provider.
1264
+ *
1265
+ * @remarks
1266
+ *
1267
+ * Can be used to compare and cache responses when doing subsequent calls.
1156
1268
  */
1157
- getLiveness(): Promise<{
1158
- status: number;
1159
- payload?: JsonValue;
1160
- }>;
1269
+ etag?: string;
1161
1270
  /**
1162
- * Get the readiness status of the backend.
1271
+ * Last modified date of the file contents.
1163
1272
  */
1164
- getReadiness(): Promise<{
1165
- status: number;
1166
- payload?: JsonValue;
1167
- }>;
1168
- }
1169
-
1273
+ lastModifiedAt?: Date;
1274
+ };
1170
1275
  /**
1171
- * The DiscoveryService is used to provide a mechanism for backend
1172
- * plugins to discover the endpoints for itself or other backend plugins.
1173
- *
1174
- * See the {@link https://backstage.io/docs/backend-system/core-services/discovery | service documentation} for more details.
1175
- *
1176
- * @remarks
1177
- *
1178
- * The purpose of the discovery API is to allow for many different deployment
1179
- * setups and routing methods through a central configuration, instead
1180
- * of letting each individual plugin manage that configuration.
1181
- *
1182
- * Implementations of the discovery API can be as simple as a URL pattern
1183
- * using the pluginId, but could also have overrides for individual plugins,
1184
- * or query a separate discovery service.
1276
+ * An options object for {@link UrlReaderService.readTree} operations.
1185
1277
  *
1186
1278
  * @public
1187
1279
  */
1188
- interface DiscoveryService {
1280
+ type UrlReaderServiceReadTreeOptions = {
1189
1281
  /**
1190
- * Returns the internal HTTP base URL for a given plugin, without a trailing slash.
1282
+ * A filter that can be used to select which files should be included.
1191
1283
  *
1192
1284
  * @remarks
1193
1285
  *
1194
- * The returned URL should point to an internal endpoint for the plugin, with
1195
- * the shortest route possible. The URL should be used for service-to-service
1196
- * communication within a Backstage backend deployment.
1286
+ * The path passed to the filter function is the relative path from the URL
1287
+ * that the file tree is fetched from, without any leading '/'.
1197
1288
  *
1198
- * This method must always be called just before making each request, as opposed to
1199
- * fetching the URL once when constructing an API client. That is to ensure that more
1200
- * flexible routing patterns can be supported where a different result might be returned each time.
1289
+ * For example, given the URL https://github.com/my/repo/tree/master/my-dir, a file
1290
+ * at https://github.com/my/repo/blob/master/my-dir/my-subdir/my-file.txt will
1291
+ * be represented as my-subdir/my-file.txt
1201
1292
  *
1202
- * For example, asking for the URL for `catalog` may return something
1203
- * like `http://10.1.2.3/api/catalog`
1293
+ * If no filter is provided, all files are extracted.
1204
1294
  */
1205
- getBaseUrl(pluginId: string): Promise<string>;
1295
+ filter?(path: string, info?: {
1296
+ size: number;
1297
+ }): boolean;
1206
1298
  /**
1207
- * Returns the external HTTP base backend URL for a given plugin, without a trailing slash.
1299
+ * An ETag which can be provided to check whether a
1300
+ * {@link UrlReaderService.readTree} response has changed from a previous execution.
1208
1301
  *
1209
1302
  * @remarks
1210
1303
  *
1211
- * The returned URL should point to an external endpoint for the plugin, such that
1212
- * it is reachable from the Backstage frontend and other external services. The returned
1213
- * URL should be usable for example as a callback / webhook URL.
1304
+ * In the {@link UrlReaderService.readTree} response, an ETag is returned along with
1305
+ * the tree blob. The ETag is a unique identifier of the tree blob, usually
1306
+ * the commit SHA or ETag from the target.
1214
1307
  *
1215
- * The returned URL should be stable and in general not change unless other static
1216
- * or external configuration is changed. Changes should not come as a surprise
1217
- * to an operator of the Backstage backend.
1308
+ * When an ETag is given as a request option, {@link UrlReaderService.readTree} will
1309
+ * first compare the ETag against the ETag on the target branch. If they
1310
+ * match, {@link UrlReaderService.readTree} will throw a
1311
+ * {@link @backstage/errors#NotModifiedError} indicating that the response
1312
+ * will not differ from the previous response which included this particular
1313
+ * ETag. If they do not match, {@link UrlReaderService.readTree} will return the
1314
+ * rest of the response along with a new ETag.
1315
+ */
1316
+ etag?: string;
1317
+ /**
1318
+ * An abort signal to pass down to the underlying request.
1218
1319
  *
1219
- * For example, asking for the URL for `catalog` may return something
1220
- * like `https://backstage.example.com/api/catalog`
1320
+ * @remarks
1321
+ *
1322
+ * Not all reader implementations may take this field into account.
1221
1323
  */
1222
- getExternalBaseUrl(pluginId: string): Promise<string>;
1223
- }
1224
-
1324
+ signal?: AbortSignal;
1325
+ /**
1326
+ * An optional token to use for authentication when reading the resources.
1327
+ *
1328
+ * @remarks
1329
+ *
1330
+ * By default all URL Readers will use the integrations config which is supplied
1331
+ * when creating the Readers. Sometimes it might be desireable to use the already
1332
+ * created URLReaders but with a different token, maybe that's supplied by the user
1333
+ * at runtime.
1334
+ */
1335
+ token?: string;
1336
+ };
1225
1337
  /**
1226
- * Manages access to databases that plugins get.
1338
+ * Options that control {@link UrlReaderServiceReadTreeResponse.dir} execution.
1227
1339
  *
1228
- * See the {@link https://backstage.io/docs/backend-system/core-services/database | service documentation} for more details.
1340
+ * @public
1341
+ */
1342
+ type UrlReaderServiceReadTreeResponseDirOptions = {
1343
+ /**
1344
+ * The directory to write files to.
1345
+ *
1346
+ * @remarks
1347
+ *
1348
+ * Defaults to the OS tmpdir, or `backend.workingDirectory` if set in config.
1349
+ */
1350
+ targetDir?: string;
1351
+ };
1352
+ /**
1353
+ * A response object for {@link UrlReaderService.readTree} operations.
1229
1354
  *
1230
1355
  * @public
1231
1356
  */
1232
- interface DatabaseService {
1357
+ type UrlReaderServiceReadTreeResponse = {
1233
1358
  /**
1234
- * getClient provides backend plugins database connections for itself.
1359
+ * Returns an array of all the files inside the tree, and corresponding
1360
+ * functions to read their content.
1361
+ */
1362
+ files(): Promise<UrlReaderServiceReadTreeResponseFile[]>;
1363
+ /**
1364
+ * Returns the tree contents as a binary archive, using a stream.
1365
+ */
1366
+ archive(): Promise<NodeJS.ReadableStream>;
1367
+ /**
1368
+ * Extracts the tree response into a directory and returns the path of the
1369
+ * directory.
1235
1370
  *
1236
- * The purpose of this method is to allow plugins to get isolated data
1237
- * stores so that plugins are discouraged from database integration.
1371
+ * **NOTE**: It is the responsibility of the caller to remove the directory after use.
1238
1372
  */
1239
- getClient(): Promise<Knex>;
1373
+ dir(options?: UrlReaderServiceReadTreeResponseDirOptions): Promise<string>;
1240
1374
  /**
1241
- * This property is used to control the behavior of database migrations.
1375
+ * Etag returned by content provider.
1376
+ *
1377
+ * @remarks
1378
+ *
1379
+ * Can be used to compare and cache responses when doing subsequent calls.
1242
1380
  */
1243
- migrations?: {
1244
- /**
1245
- * skip database migrations. Useful if connecting to a read-only database.
1246
- *
1247
- * @defaultValue false
1248
- */
1249
- skip?: boolean;
1250
- };
1251
- }
1252
-
1381
+ etag: string;
1382
+ };
1253
1383
  /**
1254
- * Provides access to static configuration.
1255
- *
1256
- * See the {@link https://backstage.io/docs/conf/ | configuration documentation}
1257
- * and the {@link https://backstage.io/docs/backend-system/core-services/root-config | service documentation}
1258
- * for more details.
1384
+ * Represents a single file in a {@link UrlReaderService.readTree} response.
1259
1385
  *
1260
1386
  * @public
1261
1387
  */
1262
- interface RootConfigService extends Config {
1263
- }
1264
-
1388
+ type UrlReaderServiceReadTreeResponseFile = {
1389
+ /**
1390
+ * The filepath of the data.
1391
+ */
1392
+ path: string;
1393
+ /**
1394
+ * The binary contents of the file.
1395
+ */
1396
+ content(): Promise<Buffer>;
1397
+ /**
1398
+ * The last modified timestamp of the data.
1399
+ */
1400
+ lastModifiedAt?: Date;
1401
+ };
1265
1402
  /**
1266
- * Options passed to {@link CacheService.set}.
1403
+ * An options object for search operations.
1267
1404
  *
1268
1405
  * @public
1269
1406
  */
1270
- type CacheServiceSetOptions = {
1407
+ type UrlReaderServiceSearchOptions = {
1271
1408
  /**
1272
- * Optional TTL (in milliseconds if given as a number). Defaults to the TTL provided when the client
1273
- * was set up (or no TTL if none are provided).
1409
+ * An etag can be provided to check whether the search response has changed from a previous execution.
1410
+ *
1411
+ * In the search() response, an etag is returned along with the files. The etag is a unique identifier
1412
+ * of the current tree, usually the commit SHA or etag from the target.
1413
+ *
1414
+ * When an etag is given in SearchOptions, search will first compare the etag against the etag
1415
+ * on the target branch. If they match, search will throw a NotModifiedError indicating that the search
1416
+ * response will not differ from the previous response which included this particular etag. If they mismatch,
1417
+ * search will return the rest of SearchResponse along with a new etag.
1274
1418
  */
1275
- ttl?: number | HumanDuration;
1419
+ etag?: string;
1420
+ /**
1421
+ * An abort signal to pass down to the underlying request.
1422
+ *
1423
+ * @remarks
1424
+ *
1425
+ * Not all reader implementations may take this field into account.
1426
+ */
1427
+ signal?: AbortSignal;
1428
+ /**
1429
+ * An optional token to use for authentication when reading the resources.
1430
+ *
1431
+ * @remarks
1432
+ *
1433
+ * By default all URL Readers will use the integrations config which is supplied
1434
+ * when creating the Readers. Sometimes it might be desireable to use the already
1435
+ * created URLReaders but with a different token, maybe that's supplied by the user
1436
+ * at runtime.
1437
+ */
1438
+ token?: string;
1276
1439
  };
1277
1440
  /**
1278
- * Options passed to {@link CacheService.withOptions}.
1441
+ * The output of a search operation.
1279
1442
  *
1280
1443
  * @public
1281
1444
  */
1282
- type CacheServiceOptions = {
1445
+ type UrlReaderServiceSearchResponse = {
1283
1446
  /**
1284
- * An optional default TTL (in milliseconds if given as a number) to be set when getting a client
1285
- * instance. If not provided, data will persist indefinitely by default (or
1286
- * can be configured per entry at set-time).
1447
+ * The files that matched the search query.
1287
1448
  */
1288
- defaultTtl?: number | HumanDuration;
1449
+ files: UrlReaderServiceSearchResponseFile[];
1450
+ /**
1451
+ * A unique identifier of the current remote tree, usually the commit SHA or etag from the target.
1452
+ */
1453
+ etag: string;
1289
1454
  };
1290
1455
  /**
1291
- * A pre-configured, storage agnostic cache service suitable for use by
1292
- * Backstage plugins.
1293
- *
1294
- * See the {@link https://backstage.io/docs/backend-system/core-services/cache | service documentation} for more details.
1456
+ * Represents a single file in a search response.
1295
1457
  *
1296
1458
  * @public
1297
1459
  */
1298
- interface CacheService {
1299
- /**
1300
- * Reads data from a cache store for the given key. If no data was found,
1301
- * returns undefined.
1302
- */
1303
- get<TValue extends JsonValue>(key: string): Promise<TValue | undefined>;
1460
+ type UrlReaderServiceSearchResponseFile = {
1304
1461
  /**
1305
- * Writes the given data to a cache store, associated with the given key. An
1306
- * optional TTL may also be provided, otherwise it defaults to the TTL that
1307
- * was provided when the client was instantiated.
1462
+ * The full URL to the file.
1308
1463
  */
1309
- set(key: string, value: JsonValue, options?: CacheServiceSetOptions): Promise<void>;
1464
+ url: string;
1310
1465
  /**
1311
- * Removes the given key from the cache store.
1466
+ * The binary contents of the file.
1312
1467
  */
1313
- delete(key: string): Promise<void>;
1468
+ content(): Promise<Buffer>;
1314
1469
  /**
1315
- * Creates a new {@link CacheService} instance with the given options.
1470
+ * The last modified timestamp of the data.
1316
1471
  */
1317
- withOptions(options: CacheServiceOptions): CacheService;
1318
- }
1472
+ lastModifiedAt?: Date;
1473
+ };
1319
1474
 
1320
1475
  /**
1321
1476
  * Represents user information that is available to the backend, based on some
@@ -1587,6 +1742,16 @@ declare namespace coreServices {
1587
1742
  * @public
1588
1743
  */
1589
1744
  const logger: ServiceRef<LoggerService, "plugin", "singleton">;
1745
+ /**
1746
+ * Plugin-level auditing.
1747
+ *
1748
+ * See {@link AuditorService}
1749
+ * and {@link https://backstage.io/docs/backend-system/core-services/auditor | the service docs}
1750
+ * for more information.
1751
+ *
1752
+ * @public
1753
+ */
1754
+ const auditor: ServiceRef<AuditorService, "plugin", "singleton">;
1590
1755
  /**
1591
1756
  * Permission system integration for authorization of user actions.
1592
1757
  *
@@ -1597,6 +1762,16 @@ declare namespace coreServices {
1597
1762
  * @public
1598
1763
  */
1599
1764
  const permissions: ServiceRef<PermissionsService, "plugin", "singleton">;
1765
+ /**
1766
+ * Permission system integration for registering resources and permissions.
1767
+ *
1768
+ * See {@link PermissionsRegistryService}
1769
+ * and {@link https://backstage.io/docs/backend-system/core-services/permission-integrations | the service docs}
1770
+ * for more information.
1771
+ *
1772
+ * @public
1773
+ */
1774
+ const permissionsRegistry: ServiceRef<PermissionsRegistryService, "plugin", "singleton">;
1600
1775
  /**
1601
1776
  * Built-in service for accessing metadata about the current plugin.
1602
1777
  *
@@ -1845,4 +2020,4 @@ declare function createBackendFeatureLoader<TDeps extends {
1845
2020
  [name in string]: unknown;
1846
2021
  }>(options: CreateBackendFeatureLoaderOptions<TDeps>): BackendFeature;
1847
2022
 
1848
- export { type AuthService, type BackendFeature, type BackendModuleRegistrationPoints, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalAccessRestrictions, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, type CreateBackendFeatureLoaderOptions, type CreateBackendModuleOptions, type CreateBackendPluginOptions, type CreateExtensionPointOptions, type DatabaseService, type DiscoveryService, type ExtensionPoint, type HttpAuthService, type HttpRouterService, type HttpRouterServiceAuthPolicy, type LifecycleService, type LifecycleServiceShutdownHook, type LifecycleServiceShutdownOptions, type LifecycleServiceStartupHook, type LifecycleServiceStartupOptions, type LoggerService, type PermissionsService, type PermissionsServiceRequestOptions, type PluginMetadataService, type PluginServiceFactoryOptions, type RootConfigService, type RootHealthService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryOptions, type SchedulerService, type SchedulerServiceTaskDescriptor, type SchedulerServiceTaskFunction, type SchedulerServiceTaskInvocationDefinition, type SchedulerServiceTaskRunner, type SchedulerServiceTaskScheduleDefinition, type SchedulerServiceTaskScheduleDefinitionConfig, type ServiceFactory, type ServiceRef, type ServiceRefOptions, type UrlReaderService, type UrlReaderServiceReadTreeOptions, type UrlReaderServiceReadTreeResponse, type UrlReaderServiceReadTreeResponseDirOptions, type UrlReaderServiceReadTreeResponseFile, type UrlReaderServiceReadUrlOptions, type UrlReaderServiceReadUrlResponse, type UrlReaderServiceSearchOptions, type UrlReaderServiceSearchResponse, type UrlReaderServiceSearchResponseFile, type UserInfoService, coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };
2023
+ export { type AuditorService, type AuditorServiceCreateEventOptions, type AuditorServiceEvent, type AuditorServiceEventSeverityLevel, type AuthService, type BackendFeature, type BackendModuleRegistrationPoints, type BackendPluginRegistrationPoints, type BackstageCredentials, type BackstageNonePrincipal, type BackstagePrincipalAccessRestrictions, type BackstagePrincipalTypes, type BackstageServicePrincipal, type BackstageUserInfo, type BackstageUserPrincipal, type CacheService, type CacheServiceOptions, type CacheServiceSetOptions, type CreateBackendFeatureLoaderOptions, type CreateBackendModuleOptions, type CreateBackendPluginOptions, type CreateExtensionPointOptions, type DatabaseService, type DiscoveryService, type ExtensionPoint, type HttpAuthService, type HttpRouterService, type HttpRouterServiceAuthPolicy, type LifecycleService, type LifecycleServiceShutdownHook, type LifecycleServiceShutdownOptions, type LifecycleServiceStartupHook, type LifecycleServiceStartupOptions, type LoggerService, type PermissionsRegistryService, type PermissionsRegistryServiceAddResourceTypeOptions, type PermissionsService, type PermissionsServiceRequestOptions, type PluginMetadataService, type PluginServiceFactoryOptions, type RootConfigService, type RootHealthService, type RootHttpRouterService, type RootLifecycleService, type RootLoggerService, type RootServiceFactoryOptions, type SchedulerService, type SchedulerServiceTaskDescriptor, type SchedulerServiceTaskFunction, type SchedulerServiceTaskInvocationDefinition, type SchedulerServiceTaskRunner, type SchedulerServiceTaskScheduleDefinition, type SchedulerServiceTaskScheduleDefinitionConfig, type ServiceFactory, type ServiceRef, type ServiceRefOptions, type UrlReaderService, type UrlReaderServiceReadTreeOptions, type UrlReaderServiceReadTreeResponse, type UrlReaderServiceReadTreeResponseDirOptions, type UrlReaderServiceReadTreeResponseFile, type UrlReaderServiceReadUrlOptions, type UrlReaderServiceReadUrlResponse, type UrlReaderServiceSearchOptions, type UrlReaderServiceSearchResponse, type UrlReaderServiceSearchResponseFile, type UserInfoService, coreServices, createBackendFeatureLoader, createBackendModule, createBackendPlugin, createExtensionPoint, createServiceFactory, createServiceRef, isDatabaseConflictError, readSchedulerServiceTaskScheduleDefinitionFromConfig, resolvePackagePath, resolveSafeChildPath };