@sasjs/api 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- /* @sasjs/api 0.10.0 - the SASjs Server API, for a service worker. https://github.com/sasjs/api */
1
+ /* @sasjs/api 0.11.0 - the SASjs Server API, for a service worker. https://github.com/sasjs/api */
2
2
  "use strict";
3
3
  var SASjsApi = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -41,6 +41,7 @@ var SASjsApi = (() => {
41
41
  PROVIDER_MANAGED: () => PROVIDER_MANAGED,
42
42
  RECORD_CORPUS: () => RECORD_CORPUS,
43
43
  ROUTES: () => ROUTES,
44
+ SESSION_CORPUS: () => SESSION_CORPUS,
44
45
  STATIC_AUTHORIZED_ROUTES: () => STATIC_AUTHORIZED_ROUTES,
45
46
  TAG_CAPABILITIES: () => TAG_CAPABILITIES,
46
47
  TOP_LEVEL_ROUTES: () => TOP_LEVEL_ROUTES,
@@ -892,6 +893,14 @@ var SASjsApi = (() => {
892
893
  {
893
894
  status: 200,
894
895
  description: "Ok"
896
+ },
897
+ {
898
+ status: 400,
899
+ description: '"code" is required / "code" must be a string / "code" is not allowed to be empty'
900
+ },
901
+ {
902
+ status: 401,
903
+ description: "Unauthorized"
895
904
  }
896
905
  ]
897
906
  },
@@ -920,6 +929,14 @@ var SASjsApi = (() => {
920
929
  {
921
930
  status: 200,
922
931
  description: "Ok"
932
+ },
933
+ {
934
+ status: 400,
935
+ description: '"code" is required / "code" must be a string / "code" is not allowed to be empty'
936
+ },
937
+ {
938
+ status: 401,
939
+ description: "Unauthorized"
923
940
  }
924
941
  ]
925
942
  },
@@ -2461,7 +2478,6 @@ var SASjsApi = (() => {
2461
2478
  };
2462
2479
  var DIRECTORY = "Synchronising with an external auth provider needs a directory port, which this package does not have: a host decides which directory it holds accounts in, and answers this itself.";
2463
2480
  var RUNTIME = "Starting a program needs a runtime port, which this package does not have: a host decides which languages it holds, and answers this itself until then.";
2464
- var SESSION_RECORD = "A triggered session's record, log, output and state belong to the runtime that ran the program, and this package has no runtime port.";
2465
2481
  var HOST_CONFIG = "The body is the host's own configuration - ports, run times and providers - which a mock states for itself and this package cannot know.";
2466
2482
  var HOST_OWNED = "The host owns this report: it describes the host's own process and files, which a browser build has no equivalent of.";
2467
2483
  var WEB_BUNDLE = "The host serves its own web bundle; there is no API decision here for this package to answer.";
@@ -2639,22 +2655,13 @@ var SASjsApi = (() => {
2639
2655
  implemented: true,
2640
2656
  responses: { 200: user }
2641
2657
  },
2642
- "GET /SASjsApi/session/{sessionId}": {
2643
- implemented: false,
2644
- reason: SESSION_RECORD
2645
- },
2646
- "GET /SASjsApi/session/{sessionId}/log": {
2647
- implemented: false,
2648
- reason: SESSION_RECORD
2649
- },
2650
- "GET /SASjsApi/session/{sessionId}/output": {
2651
- implemented: false,
2652
- reason: SESSION_RECORD
2653
- },
2654
- "GET /SASjsApi/session/{sessionId}/state": {
2655
- implemented: false,
2656
- reason: SESSION_RECORD
2657
- },
2658
+ // The port takes the owner as a uid and falls back to a username, which is
2659
+ // what sasjs/server records today - a host hands its sessions through as they
2660
+ // are, and the comparison tries the identifier first.
2661
+ "GET /SASjsApi/session/{sessionId}": { implemented: true },
2662
+ "GET /SASjsApi/session/{sessionId}/log": { implemented: true },
2663
+ "GET /SASjsApi/session/{sessionId}/output": { implemented: true },
2664
+ "GET /SASjsApi/session/{sessionId}/state": { implemented: true },
2658
2665
  // STP - a stored program, on the runtime port
2659
2666
  "GET /SASjsApi/stp/execute": { implemented: false, reason: RUNTIME },
2660
2667
  "POST /SASjsApi/stp/execute": { implemented: false, reason: RUNTIME },
@@ -2811,6 +2818,14 @@ var SASjsApi = (() => {
2811
2818
  const query = request.query || {};
2812
2819
  const body = request.body || {};
2813
2820
  const params = request.params || {};
2821
+ const sessionRequired = () => {
2822
+ if (!services.session)
2823
+ throw new ApiError(
2824
+ 501,
2825
+ `This host has no session service, so it cannot answer ${routeId}.`
2826
+ );
2827
+ return services.session;
2828
+ };
2814
2829
  const required = () => {
2815
2830
  if (!records)
2816
2831
  throw new ApiError(
@@ -2910,6 +2925,43 @@ var SASjsApi = (() => {
2910
2925
  }
2911
2926
  case "GET /SASjsApi/drive/filetree":
2912
2927
  return { status: 200, body: await drive.tree(query._folderPath) };
2928
+ // ------------------------------------------------------------- sessions
2929
+ case "GET /SASjsApi/session/{sessionId}": {
2930
+ return {
2931
+ status: 200,
2932
+ body: await sessionRequired().summary(
2933
+ await caller(),
2934
+ String(params.sessionId ?? "")
2935
+ )
2936
+ };
2937
+ }
2938
+ case "GET /SASjsApi/session/{sessionId}/log": {
2939
+ return {
2940
+ status: 200,
2941
+ contents: await sessionRequired().log(
2942
+ await caller(),
2943
+ String(params.sessionId ?? "")
2944
+ )
2945
+ };
2946
+ }
2947
+ case "GET /SASjsApi/session/{sessionId}/output": {
2948
+ return {
2949
+ status: 200,
2950
+ contents: await sessionRequired().output(
2951
+ await caller(),
2952
+ String(params.sessionId ?? "")
2953
+ )
2954
+ };
2955
+ }
2956
+ case "GET /SASjsApi/session/{sessionId}/state": {
2957
+ return {
2958
+ status: 200,
2959
+ body: await sessionRequired().state(
2960
+ await caller(),
2961
+ String(params.sessionId ?? "")
2962
+ )
2963
+ };
2964
+ }
2913
2965
  // ------------------------------------------------------------- records
2914
2966
  //
2915
2967
  // The administration routes: users, groups, permission rules, clients and the
@@ -3125,6 +3177,10 @@ var SASjsApi = (() => {
3125
3177
  }
3126
3178
  };
3127
3179
  var HANDLED_ROUTES = [
3180
+ "GET /SASjsApi/session/{sessionId}",
3181
+ "GET /SASjsApi/session/{sessionId}/log",
3182
+ "GET /SASjsApi/session/{sessionId}/output",
3183
+ "GET /SASjsApi/session/{sessionId}/state",
3128
3184
  "POST /SASjsApi/code/lint",
3129
3185
  "POST /SASjsApi/code/format",
3130
3186
  "GET /SASjsApi/info/authorizedRoutes",
@@ -3662,13 +3718,50 @@ var SASjsApi = (() => {
3662
3718
  ]
3663
3719
  }
3664
3720
  },
3665
- // Two refusals are deliberately not pinned here yet: a `code` that is not a
3666
- // string, and one that is empty. The package answers 400 `"code" must be a
3667
- // string` / `"code" is not allowed to be empty` - the messages the server's
3668
- // schema produces - but sasjs/server's code controller carries no
3669
- // `@Response(400)` for these routes, so the document states 200 alone and the
3670
- // parity gate refuses a case answering anything else. The cases land when the
3671
- // decorators do.
3721
+ {
3722
+ id: "code-lint-unauthenticated",
3723
+ route: "POST /SASjsApi/code/lint",
3724
+ description: "refuses a caller with no token",
3725
+ request: { body: { code: "data _null_; run;" } },
3726
+ expect: { status: 401, error: "Unauthorized" }
3727
+ },
3728
+ {
3729
+ id: "code-lint-non-string",
3730
+ route: "POST /SASjsApi/code/lint",
3731
+ description: "refuses a code value that is not a string, rather than coercing it",
3732
+ request: {
3733
+ subject: { userId: "user-admin", clientId: "web_app" },
3734
+ body: { code: 123 }
3735
+ },
3736
+ expect: { status: 400, error: '"code" must be a string' }
3737
+ },
3738
+ {
3739
+ id: "code-lint-empty",
3740
+ route: "POST /SASjsApi/code/lint",
3741
+ description: "refuses an empty buffer, which is not the same as a missing one",
3742
+ request: {
3743
+ subject: { userId: "user-admin", clientId: "web_app" },
3744
+ body: { code: "" }
3745
+ },
3746
+ expect: { status: 400, error: '"code" is not allowed to be empty' }
3747
+ },
3748
+ {
3749
+ id: "code-format-unauthenticated",
3750
+ route: "POST /SASjsApi/code/format",
3751
+ description: "refuses a caller with no token",
3752
+ request: { body: { code: "data _null_; run;" } },
3753
+ expect: { status: 401, error: "Unauthorized" }
3754
+ },
3755
+ {
3756
+ id: "code-format-non-string",
3757
+ route: "POST /SASjsApi/code/format",
3758
+ description: "refuses a code value that is not a string",
3759
+ request: {
3760
+ subject: { userId: "user-admin", clientId: "web_app" },
3761
+ body: { code: 123 }
3762
+ },
3763
+ expect: { status: 400, error: '"code" must be a string' }
3764
+ },
3672
3765
  {
3673
3766
  id: "code-format-adds-the-header",
3674
3767
  route: "POST /SASjsApi/code/format",
@@ -4805,6 +4898,78 @@ var SASjsApi = (() => {
4805
4898
  }
4806
4899
  ];
4807
4900
 
4901
+ // src/corpus/session.ts
4902
+ var ADMIN = { userId: "user-admin", clientId: "web_app" };
4903
+ var RESTRICTED = { userId: "user-restricted", clientId: "web_app" };
4904
+ var SESSION_CORPUS = [
4905
+ {
4906
+ id: "session-summary-own",
4907
+ route: "GET /SASjsApi/session/{sessionId}",
4908
+ description: "answers the owner the summary of their own session",
4909
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4910
+ expect: {
4911
+ status: 200,
4912
+ body: {
4913
+ sessionId: "sess-admin",
4914
+ state: "completed",
4915
+ pid: 4242,
4916
+ creationTimeStamp: "2026-11-07T09:00:00.000Z",
4917
+ deathTimeStamp: "2026-11-07T09:00:04.000Z",
4918
+ expiresAfterMins: 60
4919
+ }
4920
+ }
4921
+ },
4922
+ {
4923
+ id: "session-summary-as-admin",
4924
+ route: "GET /SASjsApi/session/{sessionId}",
4925
+ description: "answers an administrator another account's session",
4926
+ request: { subject: ADMIN, params: { sessionId: "sess-restricted" } },
4927
+ expect: {
4928
+ status: 200,
4929
+ body: {
4930
+ sessionId: "sess-restricted",
4931
+ state: "running",
4932
+ pid: 4243,
4933
+ creationTimeStamp: "2026-11-07T09:05:00.000Z"
4934
+ }
4935
+ }
4936
+ },
4937
+ {
4938
+ id: "session-log-own",
4939
+ route: "GET /SASjsApi/session/{sessionId}/log",
4940
+ description: "answers the log this session wrote",
4941
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4942
+ expect: {
4943
+ status: 200,
4944
+ contents: "NOTE: session started\nNOTE: session completed\n"
4945
+ }
4946
+ },
4947
+ {
4948
+ id: "session-log-nothing-written",
4949
+ route: "GET /SASjsApi/session/{sessionId}/log",
4950
+ description: "answers an empty body for a session that has written nothing",
4951
+ request: { subject: ADMIN, params: { sessionId: "sess-silent" } },
4952
+ expect: { status: 200, contents: "" }
4953
+ },
4954
+ {
4955
+ id: "session-output-own",
4956
+ route: "GET /SASjsApi/session/{sessionId}/output",
4957
+ description: "answers the webout this session produced",
4958
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4959
+ expect: { status: 200, contents: "<html><body>42</body></html>" }
4960
+ },
4961
+ {
4962
+ id: "session-state-own",
4963
+ route: "GET /SASjsApi/session/{sessionId}/state",
4964
+ description: "answers the run time's state for this session",
4965
+ request: { subject: RESTRICTED, params: { sessionId: "sess-restricted" } },
4966
+ expect: {
4967
+ status: 200,
4968
+ body: { state: "running", pid: 4243, lineCount: 3 }
4969
+ }
4970
+ }
4971
+ ];
4972
+
4808
4973
  // src/corpus/records.ts
4809
4974
  var SIGNED_IN_TOKENS = [
4810
4975
  {
@@ -4867,8 +5032,8 @@ var SASjsApi = (() => {
4867
5032
  }
4868
5033
  ]
4869
5034
  };
4870
- var ADMIN = "admin-access";
4871
- var RESTRICTED = "user-access";
5035
+ var ADMIN2 = "admin-access";
5036
+ var RESTRICTED2 = "user-access";
4872
5037
  var RESTRICTED_UID = "user-restricted";
4873
5038
  var ADMIN_UID = "user-admin";
4874
5039
  var RECORD_CORPUS = [
@@ -4878,7 +5043,7 @@ var SASjsApi = (() => {
4878
5043
  route: "GET /SASjsApi/user",
4879
5044
  description: "lists the accounts any signed-in caller may see",
4880
5045
  identity: ADMIN_SIGNED_IN,
4881
- request: { token: ADMIN },
5046
+ request: { token: ADMIN2 },
4882
5047
  expect: {
4883
5048
  status: 200,
4884
5049
  body: [
@@ -4902,7 +5067,7 @@ var SASjsApi = (() => {
4902
5067
  route: "GET /SASjsApi/user/{uid}",
4903
5068
  description: "returns the caller their own details, with the auto-exec code",
4904
5069
  identity: ADMIN_SIGNED_IN,
4905
- request: { token: RESTRICTED, params: { uid: RESTRICTED_UID } },
5070
+ request: { token: RESTRICTED2, params: { uid: RESTRICTED_UID } },
4906
5071
  expect: {
4907
5072
  status: 200,
4908
5073
  partial: {
@@ -4927,7 +5092,7 @@ var SASjsApi = (() => {
4927
5092
  route: "GET /SASjsApi/user/{uid}",
4928
5093
  description: "answers 404 for an identifier no account has",
4929
5094
  identity: ADMIN_SIGNED_IN,
4930
- request: { token: ADMIN, params: { uid: "user-none" } },
5095
+ request: { token: ADMIN2, params: { uid: "user-none" } },
4931
5096
  expect: { status: 404, error: "User is not found." }
4932
5097
  },
4933
5098
  {
@@ -4935,7 +5100,7 @@ var SASjsApi = (() => {
4935
5100
  route: "GET /SASjsApi/user/by/username/{username}",
4936
5101
  description: "finds an account by username",
4937
5102
  identity: ADMIN_SIGNED_IN,
4938
- request: { token: ADMIN, params: { username: "user2" } },
5103
+ request: { token: ADMIN2, params: { username: "user2" } },
4939
5104
  expect: {
4940
5105
  status: 200,
4941
5106
  partial: { uid: RESTRICTED_UID, username: "user2", isAdmin: false }
@@ -4954,7 +5119,7 @@ var SASjsApi = (() => {
4954
5119
  route: "GET /SASjsApi/user/by/username/{username}",
4955
5120
  description: "answers 404 for a username no account has",
4956
5121
  identity: ADMIN_SIGNED_IN,
4957
- request: { token: ADMIN, params: { username: "nobody" } },
5122
+ request: { token: ADMIN2, params: { username: "nobody" } },
4958
5123
  expect: { status: 404, error: "User is not found." }
4959
5124
  },
4960
5125
  {
@@ -4963,7 +5128,7 @@ var SASjsApi = (() => {
4963
5128
  description: "creates an account, sanitised, and reports it",
4964
5129
  identity: ADMIN_SIGNED_IN,
4965
5130
  request: {
4966
- token: ADMIN,
5131
+ token: ADMIN2,
4967
5132
  body: {
4968
5133
  username: "newuser",
4969
5134
  displayName: " New User ",
@@ -4988,7 +5153,7 @@ var SASjsApi = (() => {
4988
5153
  description: "refuses a creation by a caller who is not an administrator",
4989
5154
  identity: ADMIN_SIGNED_IN,
4990
5155
  request: {
4991
- token: RESTRICTED,
5156
+ token: RESTRICTED2,
4992
5157
  body: {
4993
5158
  username: "newuser",
4994
5159
  displayName: "New User",
@@ -5011,7 +5176,7 @@ var SASjsApi = (() => {
5011
5176
  description: "refuses a username that is taken",
5012
5177
  identity: ADMIN_SIGNED_IN,
5013
5178
  request: {
5014
- token: ADMIN,
5179
+ token: ADMIN2,
5015
5180
  body: { username: "user2", displayName: "Another", password: "newpass" }
5016
5181
  },
5017
5182
  expect: { status: 409, error: "Username already exists." }
@@ -5022,7 +5187,7 @@ var SASjsApi = (() => {
5022
5187
  description: "changes an account's display name",
5023
5188
  identity: ADMIN_SIGNED_IN,
5024
5189
  request: {
5025
- token: ADMIN,
5190
+ token: ADMIN2,
5026
5191
  params: { uid: RESTRICTED_UID },
5027
5192
  body: {
5028
5193
  displayName: "Renamed User",
@@ -5041,7 +5206,7 @@ var SASjsApi = (() => {
5041
5206
  description: "refuses a change to somebody else's account",
5042
5207
  identity: ADMIN_SIGNED_IN,
5043
5208
  request: {
5044
- token: RESTRICTED,
5209
+ token: RESTRICTED2,
5045
5210
  params: { uid: ADMIN_UID },
5046
5211
  body: { displayName: "Hijacked", username: "admin", password: "admin123" }
5047
5212
  },
@@ -5053,7 +5218,7 @@ var SASjsApi = (() => {
5053
5218
  description: "answers 404 with the identifier it looked up",
5054
5219
  identity: ADMIN_SIGNED_IN,
5055
5220
  request: {
5056
- token: ADMIN,
5221
+ token: ADMIN2,
5057
5222
  params: { uid: "user-none" },
5058
5223
  body: { displayName: "Nobody", username: "nobody", password: "none123" }
5059
5224
  },
@@ -5065,7 +5230,7 @@ var SASjsApi = (() => {
5065
5230
  description: "refuses a username change on a provider-managed account",
5066
5231
  identity: PROVIDER_MANAGED,
5067
5232
  request: {
5068
- token: ADMIN,
5233
+ token: ADMIN2,
5069
5234
  params: { uid: "user-directory" },
5070
5235
  body: {
5071
5236
  username: "renamed",
@@ -5084,7 +5249,7 @@ var SASjsApi = (() => {
5084
5249
  description: "refuses a username another account already has",
5085
5250
  identity: ADMIN_SIGNED_IN,
5086
5251
  request: {
5087
- token: ADMIN,
5252
+ token: ADMIN2,
5088
5253
  params: { uid: RESTRICTED_UID },
5089
5254
  body: { username: "admin", displayName: "Demo User", password: "user123" }
5090
5255
  },
@@ -5096,7 +5261,7 @@ var SASjsApi = (() => {
5096
5261
  description: "changes an account looked up by username",
5097
5262
  identity: ADMIN_SIGNED_IN,
5098
5263
  request: {
5099
- token: ADMIN,
5264
+ token: ADMIN2,
5100
5265
  params: { username: "user2" },
5101
5266
  body: {
5102
5267
  isActive: false,
@@ -5113,7 +5278,7 @@ var SASjsApi = (() => {
5113
5278
  description: "refuses a change to another account by username",
5114
5279
  identity: ADMIN_SIGNED_IN,
5115
5280
  request: {
5116
- token: RESTRICTED,
5281
+ token: RESTRICTED2,
5117
5282
  params: { username: "admin" },
5118
5283
  body: { displayName: "Hijacked", username: "admin", password: "admin123" }
5119
5284
  },
@@ -5125,7 +5290,7 @@ var SASjsApi = (() => {
5125
5290
  description: "answers 404 with the username it looked up",
5126
5291
  identity: ADMIN_SIGNED_IN,
5127
5292
  request: {
5128
- token: ADMIN,
5293
+ token: ADMIN2,
5129
5294
  params: { username: "nobody" },
5130
5295
  body: { displayName: "Nobody", username: "nobody", password: "none123" }
5131
5296
  },
@@ -5137,7 +5302,7 @@ var SASjsApi = (() => {
5137
5302
  description: "refuses a display-name change on a provider-managed account",
5138
5303
  identity: PROVIDER_MANAGED,
5139
5304
  request: {
5140
- token: ADMIN,
5305
+ token: ADMIN2,
5141
5306
  params: { username: "diruser" },
5142
5307
  body: { displayName: "Renamed", username: "diruser", password: "dir123" }
5143
5308
  },
@@ -5152,7 +5317,7 @@ var SASjsApi = (() => {
5152
5317
  description: "refuses a username another account already has",
5153
5318
  identity: ADMIN_SIGNED_IN,
5154
5319
  request: {
5155
- token: ADMIN,
5320
+ token: ADMIN2,
5156
5321
  params: { username: "user2" },
5157
5322
  body: { username: "admin", displayName: "Demo User", password: "user123" }
5158
5323
  },
@@ -5163,7 +5328,7 @@ var SASjsApi = (() => {
5163
5328
  route: "DELETE /SASjsApi/user/{uid}",
5164
5329
  description: "deletes an account as an administrator, without a password",
5165
5330
  identity: ADMIN_SIGNED_IN,
5166
- request: { token: ADMIN, params: { uid: RESTRICTED_UID }, body: {} },
5331
+ request: { token: ADMIN2, params: { uid: RESTRICTED_UID }, body: {} },
5167
5332
  expect: { status: 200, body: "Account Deleted!" }
5168
5333
  },
5169
5334
  {
@@ -5171,7 +5336,7 @@ var SASjsApi = (() => {
5171
5336
  route: "DELETE /SASjsApi/user/{uid}",
5172
5337
  description: "refuses a deletion of somebody else's account",
5173
5338
  identity: ADMIN_SIGNED_IN,
5174
- request: { token: RESTRICTED, params: { uid: ADMIN_UID }, body: {} },
5339
+ request: { token: RESTRICTED2, params: { uid: ADMIN_UID }, body: {} },
5175
5340
  expect: { status: 401, error: "Admin account required" }
5176
5341
  },
5177
5342
  {
@@ -5179,7 +5344,7 @@ var SASjsApi = (() => {
5179
5344
  route: "DELETE /SASjsApi/user/{uid}",
5180
5345
  description: "answers 404 for an identifier no account has",
5181
5346
  identity: ADMIN_SIGNED_IN,
5182
- request: { token: ADMIN, params: { uid: "user-none" }, body: {} },
5347
+ request: { token: ADMIN2, params: { uid: "user-none" }, body: {} },
5183
5348
  expect: { status: 404, error: "User is not found." }
5184
5349
  },
5185
5350
  {
@@ -5188,7 +5353,7 @@ var SASjsApi = (() => {
5188
5353
  description: "deletes an account looked up by username",
5189
5354
  identity: ADMIN_SIGNED_IN,
5190
5355
  request: {
5191
- token: ADMIN,
5356
+ token: ADMIN2,
5192
5357
  params: { username: "user2" },
5193
5358
  body: {}
5194
5359
  },
@@ -5200,7 +5365,7 @@ var SASjsApi = (() => {
5200
5365
  description: "refuses a self-deletion whose password is wrong",
5201
5366
  identity: ADMIN_SIGNED_IN,
5202
5367
  request: {
5203
- token: RESTRICTED,
5368
+ token: RESTRICTED2,
5204
5369
  params: { username: "user2" },
5205
5370
  body: { password: "wrong123" }
5206
5371
  },
@@ -5211,7 +5376,7 @@ var SASjsApi = (() => {
5211
5376
  route: "DELETE /SASjsApi/user/by/username/{username}",
5212
5377
  description: "answers 404 for a username no account has",
5213
5378
  identity: ADMIN_SIGNED_IN,
5214
- request: { token: ADMIN, params: { username: "nobody" }, body: {} },
5379
+ request: { token: ADMIN2, params: { username: "nobody" }, body: {} },
5215
5380
  expect: { status: 404, error: "User is not found." }
5216
5381
  },
5217
5382
  // ----------------------------------------------------------------- groups
@@ -5220,7 +5385,7 @@ var SASjsApi = (() => {
5220
5385
  route: "GET /SASjsApi/group",
5221
5386
  description: "lists the groups",
5222
5387
  identity: ADMIN_SIGNED_IN,
5223
- request: { token: RESTRICTED },
5388
+ request: { token: RESTRICTED2 },
5224
5389
  expect: {
5225
5390
  status: 200,
5226
5391
  body: [
@@ -5242,7 +5407,7 @@ var SASjsApi = (() => {
5242
5407
  route: "GET /SASjsApi/group/{uid}",
5243
5408
  description: "returns a group and its members",
5244
5409
  identity: ADMIN_SIGNED_IN,
5245
- request: { token: RESTRICTED, params: { uid: "group-admins" } },
5410
+ request: { token: RESTRICTED2, params: { uid: "group-admins" } },
5246
5411
  expect: {
5247
5412
  status: 200,
5248
5413
  partial: {
@@ -5265,7 +5430,7 @@ var SASjsApi = (() => {
5265
5430
  route: "GET /SASjsApi/group/{uid}",
5266
5431
  description: "answers 404 for an identifier no group has",
5267
5432
  identity: ADMIN_SIGNED_IN,
5268
- request: { token: ADMIN, params: { uid: "group-none" } },
5433
+ request: { token: ADMIN2, params: { uid: "group-none" } },
5269
5434
  expect: { status: 404, error: "Group not found." }
5270
5435
  },
5271
5436
  {
@@ -5273,7 +5438,7 @@ var SASjsApi = (() => {
5273
5438
  route: "GET /SASjsApi/group/by/groupname/{name}",
5274
5439
  description: "finds a group by name",
5275
5440
  identity: ADMIN_SIGNED_IN,
5276
- request: { token: ADMIN, params: { name: "DCGroup" } },
5441
+ request: { token: ADMIN2, params: { name: "DCGroup" } },
5277
5442
  expect: {
5278
5443
  status: 200,
5279
5444
  partial: { uid: "group-data-controller", name: "DCGroup" }
@@ -5284,7 +5449,7 @@ var SASjsApi = (() => {
5284
5449
  route: "GET /SASjsApi/group/by/groupname/{name}",
5285
5450
  description: "answers 404 for a name no group has",
5286
5451
  identity: ADMIN_SIGNED_IN,
5287
- request: { token: ADMIN, params: { name: "nope" } },
5452
+ request: { token: ADMIN2, params: { name: "nope" } },
5288
5453
  expect: { status: 404, error: "Group not found." }
5289
5454
  },
5290
5455
  {
@@ -5293,7 +5458,7 @@ var SASjsApi = (() => {
5293
5458
  description: "creates a group with no members",
5294
5459
  identity: ADMIN_SIGNED_IN,
5295
5460
  request: {
5296
- token: ADMIN,
5461
+ token: ADMIN2,
5297
5462
  body: { name: "NewGroup", description: "A new group", isActive: true }
5298
5463
  },
5299
5464
  expect: {
@@ -5312,7 +5477,7 @@ var SASjsApi = (() => {
5312
5477
  description: "refuses a creation by a caller who is not an administrator",
5313
5478
  identity: ADMIN_SIGNED_IN,
5314
5479
  request: {
5315
- token: RESTRICTED,
5480
+ token: RESTRICTED2,
5316
5481
  body: { name: "NewGroup", description: "x" }
5317
5482
  },
5318
5483
  expect: { status: 401, error: "Admin account required" }
@@ -5322,7 +5487,7 @@ var SASjsApi = (() => {
5322
5487
  route: "POST /SASjsApi/group",
5323
5488
  description: "refuses a name that is taken",
5324
5489
  identity: ADMIN_SIGNED_IN,
5325
- request: { token: ADMIN, body: { name: "DCGroup", description: "again" } },
5490
+ request: { token: ADMIN2, body: { name: "DCGroup", description: "again" } },
5326
5491
  expect: { status: 409, error: "Group name already exists." }
5327
5492
  },
5328
5493
  {
@@ -5331,7 +5496,7 @@ var SASjsApi = (() => {
5331
5496
  description: "adds a member and returns the group",
5332
5497
  identity: ADMIN_SIGNED_IN,
5333
5498
  request: {
5334
- token: ADMIN,
5499
+ token: ADMIN2,
5335
5500
  params: { groupUid: "group-admins", userUid: RESTRICTED_UID }
5336
5501
  },
5337
5502
  expect: {
@@ -5345,7 +5510,7 @@ var SASjsApi = (() => {
5345
5510
  description: "refuses a change to the reserved public group",
5346
5511
  identity: PROVIDER_MANAGED,
5347
5512
  request: {
5348
- token: ADMIN,
5513
+ token: ADMIN2,
5349
5514
  params: { groupUid: "group-public", userUid: RESTRICTED_UID }
5350
5515
  },
5351
5516
  expect: { status: 400, error: "Can't add/remove user to 'public' group." }
@@ -5356,7 +5521,7 @@ var SASjsApi = (() => {
5356
5521
  description: "refuses a membership change by a non-administrator",
5357
5522
  identity: ADMIN_SIGNED_IN,
5358
5523
  request: {
5359
- token: RESTRICTED,
5524
+ token: RESTRICTED2,
5360
5525
  params: { groupUid: "group-admins", userUid: RESTRICTED_UID }
5361
5526
  },
5362
5527
  expect: { status: 401, error: "Admin account required" }
@@ -5367,7 +5532,7 @@ var SASjsApi = (() => {
5367
5532
  description: "answers 404 for a group that does not exist",
5368
5533
  identity: ADMIN_SIGNED_IN,
5369
5534
  request: {
5370
- token: ADMIN,
5535
+ token: ADMIN2,
5371
5536
  params: { groupUid: "group-none", userUid: RESTRICTED_UID }
5372
5537
  },
5373
5538
  expect: { status: 404, error: "Group not found." }
@@ -5378,7 +5543,7 @@ var SASjsApi = (() => {
5378
5543
  description: "refuses a membership change on a provider-managed group",
5379
5544
  identity: PROVIDER_MANAGED,
5380
5545
  request: {
5381
- token: ADMIN,
5546
+ token: ADMIN2,
5382
5547
  params: { groupUid: "group-directory", userUid: RESTRICTED_UID }
5383
5548
  },
5384
5549
  expect: {
@@ -5392,7 +5557,7 @@ var SASjsApi = (() => {
5392
5557
  description: "removes a member and returns the group",
5393
5558
  identity: ADMIN_SIGNED_IN,
5394
5559
  request: {
5395
- token: ADMIN,
5560
+ token: ADMIN2,
5396
5561
  params: { groupUid: "group-data-controller", userUid: RESTRICTED_UID }
5397
5562
  },
5398
5563
  expect: {
@@ -5406,7 +5571,7 @@ var SASjsApi = (() => {
5406
5571
  description: "refuses a membership change for a provider-managed user",
5407
5572
  identity: PROVIDER_MANAGED,
5408
5573
  request: {
5409
- token: ADMIN,
5574
+ token: ADMIN2,
5410
5575
  params: { groupUid: "group-admins", userUid: "user-directory" }
5411
5576
  },
5412
5577
  expect: {
@@ -5420,7 +5585,7 @@ var SASjsApi = (() => {
5420
5585
  description: "refuses a membership change for a provider-managed user",
5421
5586
  identity: PROVIDER_MANAGED,
5422
5587
  request: {
5423
- token: ADMIN,
5588
+ token: ADMIN2,
5424
5589
  params: { groupUid: "group-admins", userUid: "user-directory" }
5425
5590
  },
5426
5591
  expect: {
@@ -5434,7 +5599,7 @@ var SASjsApi = (() => {
5434
5599
  description: "refuses a change to the reserved public group",
5435
5600
  identity: PROVIDER_MANAGED,
5436
5601
  request: {
5437
- token: ADMIN,
5602
+ token: ADMIN2,
5438
5603
  params: { groupUid: "group-public", userUid: RESTRICTED_UID }
5439
5604
  },
5440
5605
  expect: { status: 400, error: "Can't add/remove user to 'public' group." }
@@ -5445,7 +5610,7 @@ var SASjsApi = (() => {
5445
5610
  description: "refuses a membership change by a non-administrator",
5446
5611
  identity: ADMIN_SIGNED_IN,
5447
5612
  request: {
5448
- token: RESTRICTED,
5613
+ token: RESTRICTED2,
5449
5614
  params: { groupUid: "group-data-controller", userUid: RESTRICTED_UID }
5450
5615
  },
5451
5616
  expect: { status: 401, error: "Admin account required" }
@@ -5456,7 +5621,7 @@ var SASjsApi = (() => {
5456
5621
  description: "answers 404 for a member that does not exist",
5457
5622
  identity: ADMIN_SIGNED_IN,
5458
5623
  request: {
5459
- token: ADMIN,
5624
+ token: ADMIN2,
5460
5625
  params: { groupUid: "group-admins", userUid: "user-none" }
5461
5626
  },
5462
5627
  expect: { status: 404, error: "User not found." }
@@ -5467,7 +5632,7 @@ var SASjsApi = (() => {
5467
5632
  description: "refuses a membership change on a provider-managed group",
5468
5633
  identity: PROVIDER_MANAGED,
5469
5634
  request: {
5470
- token: ADMIN,
5635
+ token: ADMIN2,
5471
5636
  params: { groupUid: "group-directory", userUid: RESTRICTED_UID }
5472
5637
  },
5473
5638
  expect: {
@@ -5480,7 +5645,7 @@ var SASjsApi = (() => {
5480
5645
  route: "DELETE /SASjsApi/group/{uid}",
5481
5646
  description: "deletes a group",
5482
5647
  identity: ADMIN_SIGNED_IN,
5483
- request: { token: ADMIN, params: { uid: "group-data-controller" } },
5648
+ request: { token: ADMIN2, params: { uid: "group-data-controller" } },
5484
5649
  expect: { status: 200 }
5485
5650
  },
5486
5651
  {
@@ -5488,7 +5653,7 @@ var SASjsApi = (() => {
5488
5653
  route: "DELETE /SASjsApi/group/{uid}",
5489
5654
  description: "refuses a deletion by a caller who is not an administrator",
5490
5655
  identity: ADMIN_SIGNED_IN,
5491
- request: { token: RESTRICTED, params: { uid: "group-admins" } },
5656
+ request: { token: RESTRICTED2, params: { uid: "group-admins" } },
5492
5657
  expect: { status: 401, error: "Admin account required" }
5493
5658
  },
5494
5659
  {
@@ -5496,7 +5661,7 @@ var SASjsApi = (() => {
5496
5661
  route: "DELETE /SASjsApi/group/{uid}",
5497
5662
  description: "answers 404 for an identifier no group has",
5498
5663
  identity: ADMIN_SIGNED_IN,
5499
- request: { token: ADMIN, params: { uid: "group-none" } },
5664
+ request: { token: ADMIN2, params: { uid: "group-none" } },
5500
5665
  expect: { status: 404, error: "Group not found." }
5501
5666
  },
5502
5667
  // ------------------------------------------------------------ permissions
@@ -5505,7 +5670,7 @@ var SASjsApi = (() => {
5505
5670
  route: "GET /SASjsApi/info/authorizedRoutes",
5506
5671
  description: "answers the routes that accept a rule, to any caller",
5507
5672
  identity: ADMIN_SIGNED_IN,
5508
- request: { token: RESTRICTED },
5673
+ request: { token: RESTRICTED2 },
5509
5674
  expect: {
5510
5675
  status: 200,
5511
5676
  body: {
@@ -5529,7 +5694,7 @@ var SASjsApi = (() => {
5529
5694
  route: "GET /SASjsApi/info/myAuthorizedRoutes",
5530
5695
  description: "answers every route to an administrator",
5531
5696
  identity: ADMIN_SIGNED_IN,
5532
- request: { token: ADMIN },
5697
+ request: { token: ADMIN2 },
5533
5698
  expect: {
5534
5699
  status: 200,
5535
5700
  body: {
@@ -5553,7 +5718,7 @@ var SASjsApi = (() => {
5553
5718
  route: "GET /SASjsApi/info/myAuthorizedRoutes",
5554
5719
  description: "answers a caller only the routes its rules grant",
5555
5720
  identity: ADMIN_SIGNED_IN,
5556
- request: { token: RESTRICTED },
5721
+ request: { token: RESTRICTED2 },
5557
5722
  expect: {
5558
5723
  status: 200,
5559
5724
  // /AppStream is visible whatever the rules say; the two grants come from
@@ -5569,7 +5734,7 @@ var SASjsApi = (() => {
5569
5734
  route: "GET /SASjsApi/permission",
5570
5735
  description: "returns every rule to an administrator",
5571
5736
  identity: ADMIN_SIGNED_IN,
5572
- request: { token: ADMIN },
5737
+ request: { token: ADMIN2 },
5573
5738
  expect: {
5574
5739
  status: 200,
5575
5740
  body: [
@@ -5602,7 +5767,7 @@ var SASjsApi = (() => {
5602
5767
  route: "GET /SASjsApi/permission",
5603
5768
  description: "returns a caller only their own rules and their groups'",
5604
5769
  identity: ADMIN_SIGNED_IN,
5605
- request: { token: RESTRICTED },
5770
+ request: { token: RESTRICTED2 },
5606
5771
  expect: {
5607
5772
  status: 200,
5608
5773
  body: [
@@ -5644,7 +5809,7 @@ var SASjsApi = (() => {
5644
5809
  description: "creates a rule for a user",
5645
5810
  identity: ADMIN_SIGNED_IN,
5646
5811
  request: {
5647
- token: ADMIN,
5812
+ token: ADMIN2,
5648
5813
  body: {
5649
5814
  path: "/SASjsApi/drive/folder",
5650
5815
  type: "Route",
@@ -5664,7 +5829,7 @@ var SASjsApi = (() => {
5664
5829
  description: "creates a rule for a group",
5665
5830
  identity: ADMIN_SIGNED_IN,
5666
5831
  request: {
5667
- token: ADMIN,
5832
+ token: ADMIN2,
5668
5833
  body: {
5669
5834
  path: "/SASjsApi/drive/rename",
5670
5835
  type: "Route",
@@ -5688,7 +5853,7 @@ var SASjsApi = (() => {
5688
5853
  description: "refuses a principal type that is neither a user nor a group",
5689
5854
  identity: ADMIN_SIGNED_IN,
5690
5855
  request: {
5691
- token: ADMIN,
5856
+ token: ADMIN2,
5692
5857
  body: {
5693
5858
  path: "/SASjsApi/drive/deploy",
5694
5859
  type: "Route",
@@ -5708,7 +5873,7 @@ var SASjsApi = (() => {
5708
5873
  description: "refuses a rule assigned to an administrator",
5709
5874
  identity: ADMIN_SIGNED_IN,
5710
5875
  request: {
5711
- token: ADMIN,
5876
+ token: ADMIN2,
5712
5877
  body: {
5713
5878
  path: "/SASjsApi/drive/folder",
5714
5879
  type: "Route",
@@ -5728,7 +5893,7 @@ var SASjsApi = (() => {
5728
5893
  description: "refuses a creation by a non-administrator",
5729
5894
  identity: ADMIN_SIGNED_IN,
5730
5895
  request: {
5731
- token: RESTRICTED,
5896
+ token: RESTRICTED2,
5732
5897
  body: {
5733
5898
  path: "/SASjsApi/drive/folder",
5734
5899
  type: "Route",
@@ -5745,7 +5910,7 @@ var SASjsApi = (() => {
5745
5910
  description: "answers 404 for a principal that does not exist",
5746
5911
  identity: ADMIN_SIGNED_IN,
5747
5912
  request: {
5748
- token: ADMIN,
5913
+ token: ADMIN2,
5749
5914
  body: {
5750
5915
  path: "/SASjsApi/drive/rename",
5751
5916
  type: "Route",
@@ -5762,7 +5927,7 @@ var SASjsApi = (() => {
5762
5927
  description: "refuses a group rule that already exists",
5763
5928
  identity: ADMIN_SIGNED_IN,
5764
5929
  request: {
5765
- token: ADMIN,
5930
+ token: ADMIN2,
5766
5931
  body: {
5767
5932
  path: "/SASjsApi/drive/file",
5768
5933
  type: "Route",
@@ -5782,7 +5947,7 @@ var SASjsApi = (() => {
5782
5947
  description: "refuses a rule that already exists",
5783
5948
  identity: ADMIN_SIGNED_IN,
5784
5949
  request: {
5785
- token: ADMIN,
5950
+ token: ADMIN2,
5786
5951
  body: {
5787
5952
  path: "/SASjsApi/code/execute",
5788
5953
  type: "Route",
@@ -5802,7 +5967,7 @@ var SASjsApi = (() => {
5802
5967
  description: "flips a rule from Deny to Grant",
5803
5968
  identity: ADMIN_SIGNED_IN,
5804
5969
  request: {
5805
- token: ADMIN,
5970
+ token: ADMIN2,
5806
5971
  params: { uid: "rule-code" },
5807
5972
  body: { setting: "Grant" }
5808
5973
  },
@@ -5814,7 +5979,7 @@ var SASjsApi = (() => {
5814
5979
  description: "refuses a change by a non-administrator",
5815
5980
  identity: ADMIN_SIGNED_IN,
5816
5981
  request: {
5817
- token: RESTRICTED,
5982
+ token: RESTRICTED2,
5818
5983
  params: { uid: "rule-code" },
5819
5984
  body: { setting: "Grant" }
5820
5985
  },
@@ -5826,7 +5991,7 @@ var SASjsApi = (() => {
5826
5991
  description: "answers 404 for a rule that does not exist",
5827
5992
  identity: ADMIN_SIGNED_IN,
5828
5993
  request: {
5829
- token: ADMIN,
5994
+ token: ADMIN2,
5830
5995
  params: { uid: "rule-none" },
5831
5996
  body: { setting: "Grant" }
5832
5997
  },
@@ -5837,7 +6002,7 @@ var SASjsApi = (() => {
5837
6002
  route: "DELETE /SASjsApi/permission/{uid}",
5838
6003
  description: "deletes a rule",
5839
6004
  identity: ADMIN_SIGNED_IN,
5840
- request: { token: ADMIN, params: { uid: "rule-code" } },
6005
+ request: { token: ADMIN2, params: { uid: "rule-code" } },
5841
6006
  expect: { status: 200, body: "Permission Deleted!" }
5842
6007
  },
5843
6008
  {
@@ -5845,7 +6010,7 @@ var SASjsApi = (() => {
5845
6010
  route: "DELETE /SASjsApi/permission/{uid}",
5846
6011
  description: "refuses a deletion by a non-administrator",
5847
6012
  identity: ADMIN_SIGNED_IN,
5848
- request: { token: RESTRICTED, params: { uid: "rule-code" } },
6013
+ request: { token: RESTRICTED2, params: { uid: "rule-code" } },
5849
6014
  expect: { status: 401, error: "Admin account required" }
5850
6015
  },
5851
6016
  {
@@ -5853,7 +6018,7 @@ var SASjsApi = (() => {
5853
6018
  route: "DELETE /SASjsApi/permission/{uid}",
5854
6019
  description: "answers 404 for a rule that does not exist",
5855
6020
  identity: ADMIN_SIGNED_IN,
5856
- request: { token: ADMIN, params: { uid: "rule-none" } },
6021
+ request: { token: ADMIN2, params: { uid: "rule-none" } },
5857
6022
  expect: { status: 404, error: "Permission not found." }
5858
6023
  },
5859
6024
  // --------------------------------------------------------------- clients
@@ -5862,7 +6027,7 @@ var SASjsApi = (() => {
5862
6027
  route: "GET /SASjsApi/client",
5863
6028
  description: "lists the registered clients",
5864
6029
  identity: ADMIN_SIGNED_IN,
5865
- request: { token: ADMIN },
6030
+ request: { token: ADMIN2 },
5866
6031
  expect: {
5867
6032
  status: 200,
5868
6033
  body: [
@@ -5886,7 +6051,7 @@ var SASjsApi = (() => {
5886
6051
  route: "GET /SASjsApi/client",
5887
6052
  description: "refuses the list to a caller who is not an administrator",
5888
6053
  identity: ADMIN_SIGNED_IN,
5889
- request: { token: RESTRICTED },
6054
+ request: { token: RESTRICTED2 },
5890
6055
  expect: { status: 401, error: "Admin account required" }
5891
6056
  },
5892
6057
  {
@@ -5895,7 +6060,7 @@ var SASjsApi = (() => {
5895
6060
  description: "registers a client",
5896
6061
  identity: ADMIN_SIGNED_IN,
5897
6062
  request: {
5898
- token: ADMIN,
6063
+ token: ADMIN2,
5899
6064
  body: {
5900
6065
  clientId: "new_app",
5901
6066
  clientSecret: "new_secret",
@@ -5919,7 +6084,7 @@ var SASjsApi = (() => {
5919
6084
  description: "applies the schema defaults when the lifetimes are omitted",
5920
6085
  identity: ADMIN_SIGNED_IN,
5921
6086
  request: {
5922
- token: ADMIN,
6087
+ token: ADMIN2,
5923
6088
  body: { clientId: "default_app", clientSecret: "default_secret" }
5924
6089
  },
5925
6090
  expect: {
@@ -5938,7 +6103,7 @@ var SASjsApi = (() => {
5938
6103
  description: "refuses a registration by a non-administrator",
5939
6104
  identity: ADMIN_SIGNED_IN,
5940
6105
  request: {
5941
- token: RESTRICTED,
6106
+ token: RESTRICTED2,
5942
6107
  body: {
5943
6108
  clientId: "new_app",
5944
6109
  clientSecret: "new_secret",
@@ -5954,7 +6119,7 @@ var SASjsApi = (() => {
5954
6119
  description: "refuses a client id that is registered, with the 403 the server sends",
5955
6120
  identity: ADMIN_SIGNED_IN,
5956
6121
  request: {
5957
- token: ADMIN,
6122
+ token: ADMIN2,
5958
6123
  body: {
5959
6124
  clientId: "web_app",
5960
6125
  clientSecret: "other",
@@ -5971,7 +6136,7 @@ var SASjsApi = (() => {
5971
6136
  description: "changes the caller’s own password",
5972
6137
  identity: ADMIN_SIGNED_IN,
5973
6138
  request: {
5974
- token: RESTRICTED,
6139
+ token: RESTRICTED2,
5975
6140
  body: { currentPassword: "user123", newPassword: "changed123" }
5976
6141
  },
5977
6142
  expect: { status: 204 }
@@ -5981,7 +6146,7 @@ var SASjsApi = (() => {
5981
6146
  route: "PATCH /SASjsApi/auth/updatePassword",
5982
6147
  description: "refuses a body without the current password",
5983
6148
  identity: ADMIN_SIGNED_IN,
5984
- request: { token: RESTRICTED, body: { newPassword: "changed123" } },
6149
+ request: { token: RESTRICTED2, body: { newPassword: "changed123" } },
5985
6150
  expect: { status: 400, error: '"currentPassword" is required' }
5986
6151
  },
5987
6152
  {
@@ -6000,7 +6165,7 @@ var SASjsApi = (() => {
6000
6165
  description: "refuses a change whose current password is wrong",
6001
6166
  identity: ADMIN_SIGNED_IN,
6002
6167
  request: {
6003
- token: RESTRICTED,
6168
+ token: RESTRICTED2,
6004
6169
  body: { currentPassword: "wrong", newPassword: "changed123" }
6005
6170
  },
6006
6171
  expect: { status: 403, error: "Invalid current password!" }
@@ -6021,6 +6186,112 @@ var SASjsApi = (() => {
6021
6186
  }
6022
6187
  ];
6023
6188
 
6189
+ // src/session/service.ts
6190
+ var createSessionService = (store, host) => {
6191
+ const notFound = (id) => `Session with ID '${id}' was not found.`;
6192
+ const visible = async (caller, id) => {
6193
+ if (!caller) throw new ApiError(401, "Unauthorized");
6194
+ const reader = await store.userById(
6195
+ caller.userId
6196
+ );
6197
+ if (!reader || !reader.isActive) throw new ApiError(401, "Unauthorized");
6198
+ const session = await host.session(id);
6199
+ if (!session) throw new ApiError(404, notFound(id));
6200
+ const owner = session.owner;
6201
+ if (owner !== reader.uid && owner !== reader.username && !reader.isAdmin)
6202
+ throw new ApiError(404, notFound(id));
6203
+ return session;
6204
+ };
6205
+ return {
6206
+ async summary(caller, id) {
6207
+ const session = await visible(caller, id);
6208
+ return session.summary;
6209
+ },
6210
+ async state(caller, id) {
6211
+ await visible(caller, id);
6212
+ const state = await host.state(id);
6213
+ if (!state) throw new ApiError(404, notFound(id));
6214
+ return state;
6215
+ },
6216
+ async log(caller, id) {
6217
+ await visible(caller, id);
6218
+ const log = await host.log(id);
6219
+ if (log === void 0) throw new ApiError(404, notFound(id));
6220
+ return log;
6221
+ },
6222
+ async output(caller, id) {
6223
+ await visible(caller, id);
6224
+ const output = await host.output(id);
6225
+ if (output === void 0) throw new ApiError(404, notFound(id));
6226
+ return output;
6227
+ }
6228
+ };
6229
+ };
6230
+
6231
+ // src/session/memory-host.ts
6232
+ var DEFAULT_SESSIONS = {
6233
+ "sess-admin": {
6234
+ owner: "user-admin",
6235
+ summary: {
6236
+ sessionId: "sess-admin",
6237
+ state: "completed",
6238
+ pid: 4242,
6239
+ creationTimeStamp: "2026-11-07T09:00:00.000Z",
6240
+ deathTimeStamp: "2026-11-07T09:00:04.000Z",
6241
+ expiresAfterMins: 60
6242
+ }
6243
+ },
6244
+ "sess-restricted": {
6245
+ owner: "user-restricted",
6246
+ summary: {
6247
+ sessionId: "sess-restricted",
6248
+ state: "running",
6249
+ pid: 4243,
6250
+ creationTimeStamp: "2026-11-07T09:05:00.000Z"
6251
+ }
6252
+ },
6253
+ "sess-silent": {
6254
+ owner: "user-admin",
6255
+ summary: {
6256
+ sessionId: "sess-silent",
6257
+ state: "running",
6258
+ pid: 4244,
6259
+ creationTimeStamp: "2026-11-07T09:10:00.000Z"
6260
+ }
6261
+ }
6262
+ };
6263
+ var STATES = {
6264
+ "sess-admin": { state: "completed", pid: 4242, lineCount: 12 },
6265
+ "sess-restricted": { state: "running", pid: 4243, lineCount: 3 }
6266
+ };
6267
+ var LOGS = {
6268
+ "sess-admin": "NOTE: session started\nNOTE: session completed\n",
6269
+ "sess-restricted": "NOTE: session started\n",
6270
+ "sess-silent": ""
6271
+ };
6272
+ var OUTPUTS = {
6273
+ "sess-admin": "<html><body>42</body></html>",
6274
+ "sess-restricted": "",
6275
+ "sess-silent": ""
6276
+ };
6277
+ var MemorySessionHost = class {
6278
+ constructor(sessions = DEFAULT_SESSIONS) {
6279
+ this.sessions = sessions;
6280
+ }
6281
+ async session(id) {
6282
+ return this.sessions[id];
6283
+ }
6284
+ async state(id) {
6285
+ return STATES[id];
6286
+ }
6287
+ async log(id) {
6288
+ return LOGS[id];
6289
+ }
6290
+ async output(id) {
6291
+ return OUTPUTS[id];
6292
+ }
6293
+ };
6294
+
6024
6295
  // src/corpus/runner.ts
6025
6296
  var servicesFor = (testCase) => {
6026
6297
  const identity = new MemoryIdentityStore(
@@ -6031,7 +6302,8 @@ var SASjsApi = (() => {
6031
6302
  testCase.unwritable ? new RefusingDriveStore(testCase.seed || {}) : new MemoryDriveStore(testCase.seed || {})
6032
6303
  ),
6033
6304
  identity: createIdentityService(identity),
6034
- records: createRecordService(identity)
6305
+ records: createRecordService(identity),
6306
+ session: createSessionService(identity, new MemorySessionHost())
6035
6307
  };
6036
6308
  };
6037
6309
  var RefusingDriveStore = class extends MemoryDriveStore {