@friggframework/core 2.0.0--canary.681.2df9ef0.0 → 2.0.0--canary.683.f45da33.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.
Files changed (83) hide show
  1. package/README.md +37 -1
  2. package/application/commands/integration-commands.js +20 -10
  3. package/application/index.js +6 -2
  4. package/credential/use-cases/credential-operations-for-user.js +9 -1
  5. package/credential/use-cases/reauthorize-credential-for-user.js +14 -4
  6. package/database/encryption/encryption-schema-registry.js +7 -0
  7. package/database/organization-where.js +18 -0
  8. package/generated/prisma-mongodb/edge.js +5 -3
  9. package/generated/prisma-mongodb/index-browser.js +2 -0
  10. package/generated/prisma-mongodb/index.d.ts +115 -2
  11. package/generated/prisma-mongodb/index.js +5 -3
  12. package/generated/prisma-mongodb/package.json +1 -1
  13. package/generated/prisma-mongodb/schema.prisma +15 -0
  14. package/generated/prisma-mongodb/wasm.js +5 -3
  15. package/generated/prisma-postgresql/edge.js +5 -3
  16. package/generated/prisma-postgresql/index-browser.js +2 -0
  17. package/generated/prisma-postgresql/index.d.ts +131 -2
  18. package/generated/prisma-postgresql/index.js +5 -3
  19. package/generated/prisma-postgresql/package.json +1 -1
  20. package/generated/prisma-postgresql/schema.prisma +15 -0
  21. package/generated/prisma-postgresql/wasm.js +5 -3
  22. package/handlers/app-definition-loader.js +25 -8
  23. package/handlers/backend-utils.js +31 -25
  24. package/handlers/routers/health.js +1 -4
  25. package/handlers/workers/integration-defined-workers.js +5 -2
  26. package/index.js +10 -2
  27. package/integrations/index.js +0 -4
  28. package/integrations/integration-router.js +101 -52
  29. package/integrations/repositories/integration-not-found.js +14 -0
  30. package/integrations/repositories/integration-repository-documentdb.js +34 -3
  31. package/integrations/repositories/integration-repository-interface.js +17 -1
  32. package/integrations/repositories/integration-repository-mongo.js +59 -76
  33. package/integrations/repositories/integration-repository-postgres.js +62 -76
  34. package/integrations/tests/doubles/test-integration-repository.js +12 -1
  35. package/integrations/use-cases/create-integration.js +55 -20
  36. package/integrations/use-cases/get-integrations-for-user.js +80 -40
  37. package/integrations/use-cases/index.js +5 -1
  38. package/integrations/use-cases/integration-operations-for-user.js +55 -24
  39. package/integrations/use-cases/resolve-integration-ownership.js +177 -0
  40. package/integrations/utils/map-integration-dto.js +1 -15
  41. package/management-api/management-api-config.js +3 -0
  42. package/management-api/openapi/components.js +46 -1
  43. package/management-api/openapi/v2-operations.js +14 -1
  44. package/management-api/v2/dependencies.js +58 -14
  45. package/management-api/v2/dto.js +17 -0
  46. package/management-api/v2/handlers/authorization.js +1 -0
  47. package/management-api/v2/handlers/entities.js +10 -7
  48. package/management-api/v2/handlers/integrations.js +6 -3
  49. package/management-api/v2/request.js +32 -1
  50. package/modules/entity-scope.js +15 -0
  51. package/modules/entity-type-registry.js +311 -0
  52. package/modules/index.js +14 -0
  53. package/modules/repositories/module-repository-documentdb.js +41 -1
  54. package/modules/repositories/module-repository-interface.js +19 -2
  55. package/modules/repositories/module-repository-mongo.js +64 -73
  56. package/modules/repositories/module-repository-postgres.js +63 -73
  57. package/modules/scope-config.js +177 -0
  58. package/modules/scope-policy.js +96 -0
  59. package/modules/scope-resolution.js +288 -0
  60. package/modules/scope-visibility.js +212 -0
  61. package/modules/tests/doubles/ownership-matching.js +18 -0
  62. package/modules/use-cases/authorize-entity-for-user.js +59 -0
  63. package/modules/use-cases/entity-operations-for-user.js +50 -13
  64. package/modules/use-cases/entity-types.js +62 -14
  65. package/modules/use-cases/execute-entity-proxy-request.js +15 -0
  66. package/modules/use-cases/get-entities-for-user.js +16 -5
  67. package/modules/use-cases/get-entity-module-for-user.js +23 -3
  68. package/modules/use-cases/get-entity-options-by-id.js +5 -2
  69. package/modules/use-cases/get-module.js +5 -2
  70. package/modules/use-cases/manage-access.js +21 -0
  71. package/modules/use-cases/multi-step-authorization.js +36 -12
  72. package/modules/use-cases/process-authorization-callback.js +52 -18
  73. package/modules/use-cases/refresh-entity-options.js +5 -2
  74. package/modules/use-cases/test-module-auth.js +5 -2
  75. package/package.json +5 -5
  76. package/prisma-mongodb/schema.prisma +15 -0
  77. package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +25 -0
  78. package/prisma-postgresql/schema.prisma +15 -0
  79. package/types/index.d.ts +1 -0
  80. package/types/modules/index.d.ts +145 -0
  81. package/types/user/index.d.ts +7 -0
  82. package/user/use-cases/authenticate-user.js +7 -1
  83. package/user/user.js +24 -1
@@ -1,5 +1,6 @@
1
1
  const Boom = require('@hapi/boom');
2
2
  const { getLogger } = require('../../logs');
3
+ const { AUTH_SOURCES } = require('../user');
3
4
 
4
5
  const log = getLogger('frigg.user.authentication');
5
6
 
@@ -68,10 +69,13 @@ class AuthenticateUser {
68
69
  // Validate the API key (authentication)
69
70
  await this.authenticateWithSharedSecret.execute(apiKey);
70
71
  // Get user from x-frigg headers (authorization)
71
- return await this.getUserFromXFriggHeaders.execute(
72
+ const user = await this.getUserFromXFriggHeaders.execute(
72
73
  appUserId,
73
74
  appOrgId
74
75
  );
76
+ // The app's own backend: trusted to manage organization things.
77
+ user.setAuthSource(AUTH_SOURCES.SHARED_SECRET);
78
+ return user;
75
79
  }
76
80
  log.debug('No x-frigg-api-key header, skipping shared secret', {
77
81
  eventName: `${log.name}.shared_secret_skipped`,
@@ -90,6 +94,7 @@ class AuthenticateUser {
90
94
  // Detect JWT format (3 parts separated by dots)
91
95
  if (token && token.split('.').length === 3) {
92
96
  const user = await this.getUserFromAdopterJwt.execute(token);
97
+ user.setAuthSource(AUTH_SOURCES.ADOPTER_JWT);
93
98
  // Validate x-frigg headers match JWT claims if present
94
99
  if (appUserId || appOrgId) {
95
100
  this.validateUserMatch(user, appUserId, appOrgId);
@@ -106,6 +111,7 @@ class AuthenticateUser {
106
111
  const user = await this.getUserFromBearerToken.execute(
107
112
  req.headers.authorization
108
113
  );
114
+ user.setAuthSource(AUTH_SOURCES.BEARER_TOKEN);
109
115
  // Validate x-frigg headers match token user if present
110
116
  if (appUserId || appOrgId) {
111
117
  this.validateUserMatch(user, appUserId, appOrgId);
package/user/user.js CHANGED
@@ -1,5 +1,18 @@
1
1
  const bcrypt = require('bcryptjs');
2
2
 
3
+ /**
4
+ * How the request that produced a `User` proved who it is. Set by
5
+ * AuthenticateUser, never inferred from a missing value. Organization roles
6
+ * (ADR-056 §3, §3.6) depend on it: a shared-secret caller is the app's own
7
+ * backend and is trusted to manage; a person with a token has the role the
8
+ * token carries, or `MEMBER`.
9
+ */
10
+ const AUTH_SOURCES = Object.freeze({
11
+ SHARED_SECRET: 'shared-secret',
12
+ ADOPTER_JWT: 'adopter-jwt',
13
+ BEARER_TOKEN: 'bearer-token',
14
+ });
15
+
3
16
  /**
4
17
  * Represents a user in the system. The User class is a domain entity,
5
18
  * @class User
@@ -21,6 +34,8 @@ class User {
21
34
  // Organization role from an adopter token claim (ADR-056 §2). Per request:
22
35
  // the role stored on a membership is only what the first token carried.
23
36
  this.orgRole = null;
37
+ // How this request authenticated (one of AUTH_SOURCES); null until AuthenticateUser says.
38
+ this.authSource = null;
24
39
 
25
40
  this.config = {
26
41
  primary,
@@ -84,6 +99,14 @@ class User {
84
99
  return this.config.individualUserRequired;
85
100
  }
86
101
 
102
+ getAuthSource() {
103
+ return this.authSource;
104
+ }
105
+
106
+ setAuthSource(authSource) {
107
+ this.authSource = authSource ?? null;
108
+ }
109
+
87
110
  getOrgRole() {
88
111
  return this.orgRole;
89
112
  }
@@ -149,4 +172,4 @@ class User {
149
172
  }
150
173
  }
151
174
 
152
- module.exports = { User };
175
+ module.exports = { User, AUTH_SOURCES };