@wildo-ai/external-connectors-models 1.1.11 → 1.1.13

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 (109) hide show
  1. package/dist/esm/companion-exports.d.ts.map +1 -1
  2. package/dist/esm/companion-exports.js.map +1 -1
  3. package/dist/esm/core/commons.external-connectors-models.schemas.d.ts +10 -0
  4. package/dist/esm/core/commons.external-connectors-models.schemas.d.ts.map +1 -1
  5. package/dist/esm/core/commons.external-connectors-models.schemas.js +10 -0
  6. package/dist/esm/core/commons.external-connectors-models.schemas.js.map +1 -1
  7. package/dist/esm/core/oauth2.enums.d.ts.map +1 -1
  8. package/dist/esm/core/oauth2.enums.js.map +1 -1
  9. package/dist/esm/core/operation-classification.external-connectors-models.schemas.d.ts.map +1 -1
  10. package/dist/esm/core/operation-classification.external-connectors-models.schemas.js.map +1 -1
  11. package/dist/esm/core/operations.external-connectors-models.schemas.d.ts.map +1 -1
  12. package/dist/esm/core/operations.external-connectors-models.schemas.js.map +1 -1
  13. package/dist/esm/core/security.external-connectors-models.schemas.d.ts.map +1 -1
  14. package/dist/esm/core/security.external-connectors-models.schemas.js.map +1 -1
  15. package/dist/esm/index.d.ts +6 -0
  16. package/dist/esm/index.d.ts.map +1 -1
  17. package/dist/esm/index.js +6 -0
  18. package/dist/esm/index.js.map +1 -1
  19. package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.d.ts +20 -46
  20. package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.d.ts.map +1 -1
  21. package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.js +34 -5
  22. package/dist/esm/protocols/agent-client-protocol.external-connectors-models.schemas.js.map +1 -1
  23. package/dist/esm/protocols/billing.standard-interface.schemas.d.ts +56 -3
  24. package/dist/esm/protocols/billing.standard-interface.schemas.d.ts.map +1 -1
  25. package/dist/esm/protocols/billing.standard-interface.schemas.js +15 -2
  26. package/dist/esm/protocols/billing.standard-interface.schemas.js.map +1 -1
  27. package/dist/esm/protocols/content-safety.external-connectors-models.schemas.d.ts.map +1 -1
  28. package/dist/esm/protocols/content-safety.external-connectors-models.schemas.js.map +1 -1
  29. package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.d.ts.map +1 -1
  30. package/dist/esm/protocols/document-extraction.external-connectors-models.schemas.js.map +1 -1
  31. package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.d.ts +157 -0
  32. package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.d.ts.map +1 -0
  33. package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.js +134 -0
  34. package/dist/esm/protocols/electronic-signature.external-connectors-models.schemas.js.map +1 -0
  35. package/dist/esm/protocols/email-inbound.standard-interface.schemas.d.ts +85 -0
  36. package/dist/esm/protocols/email-inbound.standard-interface.schemas.d.ts.map +1 -1
  37. package/dist/esm/protocols/email-inbound.standard-interface.schemas.js +46 -2
  38. package/dist/esm/protocols/email-inbound.standard-interface.schemas.js.map +1 -1
  39. package/dist/esm/protocols/email.external-connectors-models.schemas.d.ts.map +1 -1
  40. package/dist/esm/protocols/email.external-connectors-models.schemas.js.map +1 -1
  41. package/dist/esm/protocols/email.standard-interface.schemas.d.ts.map +1 -1
  42. package/dist/esm/protocols/email.standard-interface.schemas.js.map +1 -1
  43. package/dist/esm/protocols/embeddings.external-connectors-models.schemas.d.ts +49 -6
  44. package/dist/esm/protocols/embeddings.external-connectors-models.schemas.d.ts.map +1 -1
  45. package/dist/esm/protocols/embeddings.external-connectors-models.schemas.js +89 -6
  46. package/dist/esm/protocols/embeddings.external-connectors-models.schemas.js.map +1 -1
  47. package/dist/esm/protocols/file-storage.standard-interface.d.ts +9 -2
  48. package/dist/esm/protocols/file-storage.standard-interface.d.ts.map +1 -1
  49. package/dist/esm/protocols/file-storage.standard-interface.js +6 -0
  50. package/dist/esm/protocols/file-storage.standard-interface.js.map +1 -1
  51. package/dist/esm/protocols/frontend.external-connectors-models.schemas.d.ts.map +1 -1
  52. package/dist/esm/protocols/frontend.external-connectors-models.schemas.js.map +1 -1
  53. package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.d.ts +254 -0
  54. package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.d.ts.map +1 -0
  55. package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.js +480 -0
  56. package/dist/esm/protocols/graphql-operations.external-connectors-models.schemas.js.map +1 -0
  57. package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.d.ts.map +1 -1
  58. package/dist/esm/protocols/hooks-capability.external-connectors-models.schemas.js.map +1 -1
  59. package/dist/esm/protocols/hooks.external-connectors-models.schemas.d.ts +95 -1
  60. package/dist/esm/protocols/hooks.external-connectors-models.schemas.d.ts.map +1 -1
  61. package/dist/esm/protocols/hooks.external-connectors-models.schemas.js +110 -0
  62. package/dist/esm/protocols/hooks.external-connectors-models.schemas.js.map +1 -1
  63. package/dist/esm/protocols/image.external-connectors-models.schemas.d.ts.map +1 -1
  64. package/dist/esm/protocols/image.external-connectors-models.schemas.js.map +1 -1
  65. package/dist/esm/protocols/llm.external-connectors-models.schemas.d.ts +95 -3
  66. package/dist/esm/protocols/llm.external-connectors-models.schemas.d.ts.map +1 -1
  67. package/dist/esm/protocols/llm.external-connectors-models.schemas.js +147 -15
  68. package/dist/esm/protocols/llm.external-connectors-models.schemas.js.map +1 -1
  69. package/dist/esm/protocols/oauth2-provider-assurance.definitions.d.ts.map +1 -1
  70. package/dist/esm/protocols/oauth2-provider-assurance.definitions.js.map +1 -1
  71. package/dist/esm/protocols/oauth2-provider-assurance.schemas.d.ts.map +1 -1
  72. package/dist/esm/protocols/oauth2-provider-assurance.schemas.js.map +1 -1
  73. package/dist/esm/protocols/oauth2.external-connectors-models.schemas.d.ts.map +1 -1
  74. package/dist/esm/protocols/oauth2.external-connectors-models.schemas.js.map +1 -1
  75. package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.d.ts +52 -0
  76. package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.d.ts.map +1 -0
  77. package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.js +132 -0
  78. package/dist/esm/protocols/provider-configuration-authoring.external-connectors-models.schemas.js.map +1 -0
  79. package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.d.ts +111 -0
  80. package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.d.ts.map +1 -0
  81. package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.js +203 -0
  82. package/dist/esm/protocols/provider-connection-parameters.external-connectors-models.js.map +1 -0
  83. package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts +6 -0
  84. package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts.map +1 -1
  85. package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.js +13 -7
  86. package/dist/esm/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.js.map +1 -1
  87. package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.d.ts +50 -0
  88. package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.d.ts.map +1 -0
  89. package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.js +30 -0
  90. package/dist/esm/protocols/provider-vendor-registration.external-connectors-models.js.map +1 -0
  91. package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.d.ts +730 -17
  92. package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.d.ts.map +1 -1
  93. package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.js +822 -20
  94. package/dist/esm/protocols/rest-operations.external-connectors-models.schemas.js.map +1 -1
  95. package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.d.ts +73 -0
  96. package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.d.ts.map +1 -0
  97. package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.js +82 -0
  98. package/dist/esm/protocols/service-account-token.external-connectors-models.schemas.js.map +1 -0
  99. package/dist/esm/protocols/sms.external-connectors-models.schemas.d.ts.map +1 -1
  100. package/dist/esm/protocols/sms.external-connectors-models.schemas.js.map +1 -1
  101. package/dist/esm/protocols/sms.standard-interface.schemas.d.ts +79 -1
  102. package/dist/esm/protocols/sms.standard-interface.schemas.d.ts.map +1 -1
  103. package/dist/esm/protocols/sms.standard-interface.schemas.js +93 -0
  104. package/dist/esm/protocols/sms.standard-interface.schemas.js.map +1 -1
  105. package/dist/esm/protocols/subject-erasure-effect.standard-interface.d.ts.map +1 -1
  106. package/dist/esm/protocols/subject-erasure-effect.standard-interface.js.map +1 -1
  107. package/dist/tsconfig.build.tsbuildinfo +1 -1
  108. package/package.json +5 -5
  109. package/dist/esm/.native.tsbuildinfo +0 -1
@@ -0,0 +1,203 @@
1
+ import { ProviderProtocolRuntimeKind } from '../core/commons.external-connectors-models.schemas.js';
2
+ import { classifyProviderOAuth2EndpointPlaceholders, classifyProviderOAuth2ScopePlaceholder, findProviderOAuth2EndpointTemplateDefects, findProviderOAuth2ScopeTemplateDefects, ProviderOAuth2EndpointHostAllowanceKind, ProviderOAuth2EndpointPlaceholderPosition, ProviderOAuth2ScopePlaceholderPosition, } from './rest-operations.external-connectors-models.schemas.js';
3
+ /**
4
+ * Which `{placeholders}` a person connecting an account is ASKED for: "which tenant", "which cloud", "which subdomain".
5
+ *
6
+ * ## Why these functions live here, values-free
7
+ *
8
+ * The connect screen asks for them, and since #3251 the labelling pipeline plans a word for each one
9
+ * (`providers.<ref>.connectionParameters.<name>.{label,description}`). The catalogue computes the asked set from the
10
+ * provider's runtime contract inside the application backend; the labelling planner runs in the development companion
11
+ * and must not load a provider module, so it reads the same set from the provider's discovery contribution
12
+ * (`connectionParameterNames`). Both read ONE function, {@link describeProviderAskedConnectionParameters}, so the names
13
+ * the screen asks for and the names that get words cannot disagree. Until #3251 the catalogue's rules lived privately in
14
+ * the connected-accounts controller, and a second copy of them for the contribution would have been the enumeration that
15
+ * drifts.
16
+ *
17
+ * Every function here is pure and reads the declaration only: no deployment value, no secret.
18
+ */
19
+ /**
20
+ * Every placeholder a provider's OAuth2 declaration carries, with each position it takes: across both
21
+ * endpoints (HOST / ORIGIN / PATH_OR_QUERY) and the scopes (a `{name}/…` scope makes `name` an ORIGIN).
22
+ * Whole-scope placeholders are returned separately — they form no URL component at all.
23
+ *
24
+ * One reader of "where does this name sit", shared by the connectability probe, the catalogue (which must neither
25
+ * ask for a placeholder no answer can satisfy nor render a host as a scope choice) and the discovery contribution.
26
+ * A scope with a template defect contributes nothing here; resolution refuses it. Throws when an endpoint template
27
+ * cannot be classified at all; every caller contains that per provider.
28
+ */
29
+ export function collectProviderOAuth2PlaceholderPositions(oauth2) {
30
+ const positionsByName = new Map();
31
+ const add = (name, position) => {
32
+ const positions = positionsByName.get(name) ?? new Set();
33
+ positions.add(position);
34
+ positionsByName.set(name, positions);
35
+ };
36
+ for (const url of [oauth2.authorizeUrl, oauth2.tokenUrl]) {
37
+ for (const { name, position } of classifyProviderOAuth2EndpointPlaceholders(url))
38
+ add(name, position);
39
+ }
40
+ const wholeScopeNames = new Set();
41
+ for (const scope of oauth2.scopes ?? []) {
42
+ if (findProviderOAuth2ScopeTemplateDefects(scope).length > 0)
43
+ continue;
44
+ const occurrence = classifyProviderOAuth2ScopePlaceholder(scope);
45
+ if (occurrence === undefined)
46
+ continue;
47
+ if (occurrence.position === ProviderOAuth2ScopePlaceholderPosition.WHOLE_SCOPE)
48
+ wholeScopeNames.add(occurrence.name);
49
+ else
50
+ add(occurrence.name, ProviderOAuth2EndpointPlaceholderPosition.ORIGIN);
51
+ }
52
+ return { positionsByName, wholeScopeNames };
53
+ }
54
+ /**
55
+ * The placeholders a person connecting an account through the OAuth2 flow is ASKED for.
56
+ *
57
+ * Every declared one EXCEPT those the start route would refuse whatever was typed: a host/origin
58
+ * placeholder the deployment fills (from its base URL, or from a dedicated deployment-configured host,
59
+ * #992), a host/origin placeholder the provider declares no allowance for (#623), and a whole-scope
60
+ * placeholder with no declared scope values (#991). Asking for any of them would build a form field that
61
+ * can only fail — the catalogue's `notConnectableBecause` says why instead. Absent when nothing is left
62
+ * to ask, keeping "no placeholder" distinguishable.
63
+ */
64
+ export function describeProviderOAuth2AskedConnectionParameters(oauth2) {
65
+ if (oauth2?.connectionParameters === undefined)
66
+ return undefined;
67
+ const allowances = oauth2.endpointHostAllowances ?? {};
68
+ const scopeValueAllowances = oauth2.scopeValueAllowances ?? {};
69
+ let placeholders;
70
+ try {
71
+ placeholders = collectProviderOAuth2PlaceholderPositions(oauth2);
72
+ }
73
+ catch {
74
+ // Contained with the connectability blocker (N4): endpoints that cannot even be classified leave
75
+ // nothing a person could usefully answer, and the provider already reports
76
+ // ENDPOINT_DEFINITION_INVALID. One broken definition must never fail the whole catalogue.
77
+ return undefined;
78
+ }
79
+ const asked = oauth2.connectionParameters.filter((name) => {
80
+ const allowance = Object.hasOwn(allowances, name) ? allowances[name] : undefined;
81
+ if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_BASE_URL)
82
+ return false;
83
+ if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_CONFIGURED)
84
+ return false;
85
+ // Derived from another answer (#1937): nobody chooses it, and a supplied value is refused.
86
+ if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DERIVED_FROM_CONNECTION_ANSWER)
87
+ return false;
88
+ const positions = placeholders.positionsByName.get(name);
89
+ const hostForming = positions !== undefined
90
+ && (positions.has(ProviderOAuth2EndpointPlaceholderPosition.ORIGIN) || positions.has(ProviderOAuth2EndpointPlaceholderPosition.HOST));
91
+ if (hostForming && allowance === undefined)
92
+ return false;
93
+ return !(placeholders.wholeScopeNames.has(name) && !Object.hasOwn(scopeValueAllowances, name));
94
+ });
95
+ return asked.length === 0 ? undefined : asked;
96
+ }
97
+ const NO_CREDENTIAL_BASE_URL_ANSWERS = {
98
+ asked: undefined, declared: new Set(), hostsNotDeclared: [], templateDefective: false, positionsByName: new Map(),
99
+ };
100
+ /** The same test the runtime applies before it fills a base URL through the resolver. Not global, so `test` holds no state. */
101
+ const BRACED_PLACEHOLDER = /\{[A-Za-z_][A-Za-z0-9_]*\}/;
102
+ /** Whether a provider URL template carries a `{placeholder}` the resolver fills (the test `resolveBaseUrlTemplate` applies). */
103
+ export function providerTemplateCarriesPlaceholder(template) {
104
+ return BRACED_PLACEHOLDER.test(template);
105
+ }
106
+ /**
107
+ * What a PASTED-credential vendor's base URL asks of the person connecting (#1097).
108
+ *
109
+ * The OAuth2 start asks for the placeholders its endpoints and scopes carry. A vendor with no authorization
110
+ * flow has no such endpoints, and its base URL is the one template every operation dials
111
+ * (`https://{subdomain}.zendesk.com`) — so before this door existed, a recorded and sound host allowance
112
+ * still left every call refused: nothing collected the answer. DERIVED from the contract rather than
113
+ * declared beside it, because the placeholders ARE the base URL's and the allowances are the ones
114
+ * `resolveBaseUrlTemplate` admits them against at every call; this door and that resolver read one
115
+ * declaration and cannot disagree about which names exist.
116
+ *
117
+ * The rules are {@link describeProviderOAuth2AskedConnectionParameters}'s: a path placeholder is asked freely and
118
+ * percent-encoded; a host or origin one is asked only under an allowance a person can answer (`DECLARED_VALUES`) — one
119
+ * the deployment fills is never asked, and one with NO allowance is a BLOCKER rather than a field, because the resolver
120
+ * refuses it whatever is typed. A template the classifier cannot read is contained per provider, as the
121
+ * OAuth2 case is (N4): the blocker reports it and nothing is asked.
122
+ */
123
+ export function describeProviderCredentialBaseUrlAnswers(contract) {
124
+ const baseUrl = contract?.baseUrl;
125
+ if (typeof baseUrl !== 'string' || !BRACED_PLACEHOLDER.test(baseUrl))
126
+ return NO_CREDENTIAL_BASE_URL_ANSWERS;
127
+ const allowances = contract?.baseUrlHostAllowances ?? {};
128
+ const declared = new Set(Object.keys(allowances));
129
+ let occurrences;
130
+ try {
131
+ occurrences = classifyProviderOAuth2EndpointPlaceholders(baseUrl);
132
+ }
133
+ catch {
134
+ return { ...NO_CREDENTIAL_BASE_URL_ANSWERS, declared, templateDefective: true };
135
+ }
136
+ const templateDefective = findProviderOAuth2EndpointTemplateDefects(baseUrl).length > 0;
137
+ const asked = [];
138
+ const hostsNotDeclared = [];
139
+ const positionsByName = new Map();
140
+ for (const { name, position } of occurrences) {
141
+ declared.add(name);
142
+ const positions = positionsByName.get(name) ?? new Set();
143
+ positions.add(position);
144
+ positionsByName.set(name, positions);
145
+ if (asked.includes(name) || hostsNotDeclared.includes(name))
146
+ continue;
147
+ if (position === ProviderOAuth2EndpointPlaceholderPosition.PATH_OR_QUERY) {
148
+ asked.push(name);
149
+ continue;
150
+ }
151
+ const allowance = Object.hasOwn(allowances, name) ? allowances[name] : undefined;
152
+ // A hand-authored module can carry a `null` allowance (see `hostAllowanceChoices`); it admits nothing.
153
+ if (allowance === null || typeof allowance !== 'object') {
154
+ hostsNotDeclared.push(name);
155
+ continue;
156
+ }
157
+ if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_BASE_URL)
158
+ continue;
159
+ if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_CONFIGURED)
160
+ continue;
161
+ // A host derived from another answer (#1937) is never asked. The answer it reads is KEPT when supplied, so a
162
+ // connection that chose its cloud dials that cloud's host; unanswered, the allowance's own default applies.
163
+ if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DERIVED_FROM_CONNECTION_ANSWER) {
164
+ declared.add(allowance.answer);
165
+ continue;
166
+ }
167
+ asked.push(name);
168
+ }
169
+ return { asked: asked.length === 0 ? undefined : asked, declared, hostsNotDeclared, templateDefective, positionsByName };
170
+ }
171
+ /**
172
+ * The connection parameters the connect screen ASKS for, for the connection whose REST contract this is: the OAuth2
173
+ * flow's asked placeholders when the contract declares an OAuth2 block, else the placeholders a pasted credential's base
174
+ * URL asks for (#1097). The catalogue answers `connectionParameters` with it, and the discovery contribution carries it
175
+ * as `connectionParameterNames` so the labelling pipeline plans a word for each (#3251).
176
+ *
177
+ * Pass the CONNECTION's contract: for a member of a declared shared connection, the base's, whose client connects.
178
+ */
179
+ export function describeProviderAskedConnectionParameters(contract) {
180
+ if (contract === undefined)
181
+ return undefined;
182
+ return contract.oauth2 !== undefined
183
+ ? describeProviderOAuth2AskedConnectionParameters(contract.oauth2)
184
+ : describeProviderCredentialBaseUrlAnswers(contract).asked;
185
+ }
186
+ /**
187
+ * The discovery contribution's `connectionParameterNames` (#3251): what the connect screen asks of a person connecting
188
+ * the provider's OWN connection, sorted, or `undefined` when it asks nothing. Read from the module's REST binding (the
189
+ * runtime contract of kind `ProviderProtocolRuntimeKind.REST`), the one the catalogue reads through
190
+ * `getProviderRuntimeContract(ref, REST_API)`. Pure; never throws.
191
+ *
192
+ * Every provider producer derives it with this function rather than restating the names, so the words planned for the
193
+ * screen are planned for the names it asks.
194
+ */
195
+ export function describeProviderConnectionParameterNames(protocols) {
196
+ const contract = protocols
197
+ .map((binding) => binding.runtimeContract)
198
+ .find((candidate) => candidate !== null && typeof candidate === 'object'
199
+ && candidate.kind === ProviderProtocolRuntimeKind.REST);
200
+ const asked = describeProviderAskedConnectionParameters(contract);
201
+ return asked === undefined ? undefined : [...new Set(asked)].sort((left, right) => left.localeCompare(right));
202
+ }
203
+ //# sourceMappingURL=provider-connection-parameters.external-connectors-models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-connection-parameters.external-connectors-models.js","sourceRoot":"","sources":["../../../src/protocols/provider-connection-parameters.external-connectors-models.ts"],"names":[],"mappings":"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","sourcesContent":["import { ProviderProtocolRuntimeKind } from '../core/commons.external-connectors-models.schemas';\nimport {\n classifyProviderOAuth2EndpointPlaceholders,\n classifyProviderOAuth2ScopePlaceholder,\n findProviderOAuth2EndpointTemplateDefects,\n findProviderOAuth2ScopeTemplateDefects,\n ProviderOAuth2EndpointHostAllowanceKind,\n ProviderOAuth2EndpointPlaceholderPosition,\n ProviderOAuth2ScopePlaceholderPosition,\n type ProviderRestOAuth2,\n} from './rest-operations.external-connectors-models.schemas';\n\n/**\n * Which `{placeholders}` a person connecting an account is ASKED for: \"which tenant\", \"which cloud\", \"which subdomain\".\n *\n * ## Why these functions live here, values-free\n *\n * The connect screen asks for them, and since #3251 the labelling pipeline plans a word for each one\n * (`providers.<ref>.connectionParameters.<name>.{label,description}`). The catalogue computes the asked set from the\n * provider's runtime contract inside the application backend; the labelling planner runs in the development companion\n * and must not load a provider module, so it reads the same set from the provider's discovery contribution\n * (`connectionParameterNames`). Both read ONE function, {@link describeProviderAskedConnectionParameters}, so the names\n * the screen asks for and the names that get words cannot disagree. Until #3251 the catalogue's rules lived privately in\n * the connected-accounts controller, and a second copy of them for the contribution would have been the enumeration that\n * drifts.\n *\n * Every function here is pure and reads the declaration only: no deployment value, no secret.\n */\n\n/**\n * Every placeholder a provider's OAuth2 declaration carries, with each position it takes: across both\n * endpoints (HOST / ORIGIN / PATH_OR_QUERY) and the scopes (a `{name}/…` scope makes `name` an ORIGIN).\n * Whole-scope placeholders are returned separately — they form no URL component at all.\n *\n * One reader of \"where does this name sit\", shared by the connectability probe, the catalogue (which must neither\n * ask for a placeholder no answer can satisfy nor render a host as a scope choice) and the discovery contribution.\n * A scope with a template defect contributes nothing here; resolution refuses it. Throws when an endpoint template\n * cannot be classified at all; every caller contains that per provider.\n */\nexport function collectProviderOAuth2PlaceholderPositions(oauth2: ProviderRestOAuth2): {\n readonly positionsByName: ReadonlyMap<string, ReadonlySet<ProviderOAuth2EndpointPlaceholderPosition>>;\n readonly wholeScopeNames: ReadonlySet<string>;\n} {\n const positionsByName = new Map<string, Set<ProviderOAuth2EndpointPlaceholderPosition>>();\n const add = (name: string, position: ProviderOAuth2EndpointPlaceholderPosition): void => {\n const positions = positionsByName.get(name) ?? new Set<ProviderOAuth2EndpointPlaceholderPosition>();\n positions.add(position);\n positionsByName.set(name, positions);\n };\n for (const url of [oauth2.authorizeUrl, oauth2.tokenUrl]) {\n for (const { name, position } of classifyProviderOAuth2EndpointPlaceholders(url)) add(name, position);\n }\n const wholeScopeNames = new Set<string>();\n for (const scope of oauth2.scopes ?? []) {\n if (findProviderOAuth2ScopeTemplateDefects(scope).length > 0) continue;\n const occurrence = classifyProviderOAuth2ScopePlaceholder(scope);\n if (occurrence === undefined) continue;\n if (occurrence.position === ProviderOAuth2ScopePlaceholderPosition.WHOLE_SCOPE) wholeScopeNames.add(occurrence.name);\n else add(occurrence.name, ProviderOAuth2EndpointPlaceholderPosition.ORIGIN);\n }\n return { positionsByName, wholeScopeNames };\n}\n\n/**\n * The placeholders a person connecting an account through the OAuth2 flow is ASKED for.\n *\n * Every declared one EXCEPT those the start route would refuse whatever was typed: a host/origin\n * placeholder the deployment fills (from its base URL, or from a dedicated deployment-configured host,\n * #992), a host/origin placeholder the provider declares no allowance for (#623), and a whole-scope\n * placeholder with no declared scope values (#991). Asking for any of them would build a form field that\n * can only fail — the catalogue's `notConnectableBecause` says why instead. Absent when nothing is left\n * to ask, keeping \"no placeholder\" distinguishable.\n */\nexport function describeProviderOAuth2AskedConnectionParameters(oauth2: ProviderRestOAuth2 | undefined): readonly string[] | undefined {\n if (oauth2?.connectionParameters === undefined) return undefined;\n const allowances = oauth2.endpointHostAllowances ?? {};\n const scopeValueAllowances = oauth2.scopeValueAllowances ?? {};\n let placeholders: ReturnType<typeof collectProviderOAuth2PlaceholderPositions>;\n try {\n placeholders = collectProviderOAuth2PlaceholderPositions(oauth2);\n } catch {\n // Contained with the connectability blocker (N4): endpoints that cannot even be classified leave\n // nothing a person could usefully answer, and the provider already reports\n // ENDPOINT_DEFINITION_INVALID. One broken definition must never fail the whole catalogue.\n return undefined;\n }\n const asked = oauth2.connectionParameters.filter((name) => {\n const allowance = Object.hasOwn(allowances, name) ? allowances[name] : undefined;\n if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_BASE_URL) return false;\n if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_CONFIGURED) return false;\n // Derived from another answer (#1937): nobody chooses it, and a supplied value is refused.\n if (allowance?.kind === ProviderOAuth2EndpointHostAllowanceKind.DERIVED_FROM_CONNECTION_ANSWER) return false;\n const positions = placeholders.positionsByName.get(name);\n const hostForming = positions !== undefined\n && (positions.has(ProviderOAuth2EndpointPlaceholderPosition.ORIGIN) || positions.has(ProviderOAuth2EndpointPlaceholderPosition.HOST));\n if (hostForming && allowance === undefined) return false;\n return !(placeholders.wholeScopeNames.has(name) && !Object.hasOwn(scopeValueAllowances, name));\n });\n return asked.length === 0 ? undefined : asked;\n}\n\n/**\n * The REST-contract slice the TYPED-CREDENTIAL door reads (#1097): a literal base URL that may carry\n * `{placeholder}`s, and the allowances governing the ones that form its host or origin. The same two fields\n * `http-api-provider-access.resolveBaseUrlTemplate` reads at every call.\n */\nexport interface ProviderCredentialBaseUrlContract {\n readonly baseUrl?: string;\n readonly baseUrlHostAllowances?: ProviderRestOAuth2['endpointHostAllowances'];\n}\n\n/** What a pasted-credential vendor's base URL asks of the person connecting. See {@link describeProviderCredentialBaseUrlAnswers}. */\nexport interface ProviderCredentialBaseUrlAnswers {\n /** The placeholders the person is ASKED for, in template order; `undefined` when the base URL carries none to ask. */\n readonly asked: readonly string[] | undefined;\n /** Every name the contract declares — the base URL's placeholders and every allowance key — the names an answer is kept for. */\n readonly declared: ReadonlySet<string>;\n /** Host or origin placeholders NO allowance admits: every call would refuse, and nobody connecting can fix it. */\n readonly hostsNotDeclared: readonly string[];\n /** The template cannot be resolved safely whatever is answered — two placeholders in one authority, or unreadable. */\n readonly templateDefective: boolean;\n readonly positionsByName: ReadonlyMap<string, ReadonlySet<ProviderOAuth2EndpointPlaceholderPosition>>;\n}\n\nconst NO_CREDENTIAL_BASE_URL_ANSWERS: ProviderCredentialBaseUrlAnswers = {\n asked: undefined, declared: new Set(), hostsNotDeclared: [], templateDefective: false, positionsByName: new Map(),\n};\n\n/** The same test the runtime applies before it fills a base URL through the resolver. Not global, so `test` holds no state. */\nconst BRACED_PLACEHOLDER = /\\{[A-Za-z_][A-Za-z0-9_]*\\}/;\n\n/** Whether a provider URL template carries a `{placeholder}` the resolver fills (the test `resolveBaseUrlTemplate` applies). */\nexport function providerTemplateCarriesPlaceholder(template: string): boolean {\n return BRACED_PLACEHOLDER.test(template);\n}\n\n/**\n * What a PASTED-credential vendor's base URL asks of the person connecting (#1097).\n *\n * The OAuth2 start asks for the placeholders its endpoints and scopes carry. A vendor with no authorization\n * flow has no such endpoints, and its base URL is the one template every operation dials\n * (`https://{subdomain}.zendesk.com`) — so before this door existed, a recorded and sound host allowance\n * still left every call refused: nothing collected the answer. DERIVED from the contract rather than\n * declared beside it, because the placeholders ARE the base URL's and the allowances are the ones\n * `resolveBaseUrlTemplate` admits them against at every call; this door and that resolver read one\n * declaration and cannot disagree about which names exist.\n *\n * The rules are {@link describeProviderOAuth2AskedConnectionParameters}'s: a path placeholder is asked freely and\n * percent-encoded; a host or origin one is asked only under an allowance a person can answer (`DECLARED_VALUES`) — one\n * the deployment fills is never asked, and one with NO allowance is a BLOCKER rather than a field, because the resolver\n * refuses it whatever is typed. A template the classifier cannot read is contained per provider, as the\n * OAuth2 case is (N4): the blocker reports it and nothing is asked.\n */\nexport function describeProviderCredentialBaseUrlAnswers(contract: ProviderCredentialBaseUrlContract | undefined): ProviderCredentialBaseUrlAnswers {\n const baseUrl = contract?.baseUrl;\n if (typeof baseUrl !== 'string' || !BRACED_PLACEHOLDER.test(baseUrl)) return NO_CREDENTIAL_BASE_URL_ANSWERS;\n const allowances = contract?.baseUrlHostAllowances ?? {};\n const declared = new Set<string>(Object.keys(allowances));\n let occurrences: ReturnType<typeof classifyProviderOAuth2EndpointPlaceholders>;\n try {\n occurrences = classifyProviderOAuth2EndpointPlaceholders(baseUrl);\n } catch {\n return { ...NO_CREDENTIAL_BASE_URL_ANSWERS, declared, templateDefective: true };\n }\n const templateDefective = findProviderOAuth2EndpointTemplateDefects(baseUrl).length > 0;\n const asked: string[] = [];\n const hostsNotDeclared: string[] = [];\n const positionsByName = new Map<string, Set<ProviderOAuth2EndpointPlaceholderPosition>>();\n for (const { name, position } of occurrences) {\n declared.add(name);\n const positions = positionsByName.get(name) ?? new Set<ProviderOAuth2EndpointPlaceholderPosition>();\n positions.add(position);\n positionsByName.set(name, positions);\n if (asked.includes(name) || hostsNotDeclared.includes(name)) continue;\n if (position === ProviderOAuth2EndpointPlaceholderPosition.PATH_OR_QUERY) {\n asked.push(name);\n continue;\n }\n const allowance = Object.hasOwn(allowances, name) ? allowances[name] : undefined;\n // A hand-authored module can carry a `null` allowance (see `hostAllowanceChoices`); it admits nothing.\n if (allowance === null || typeof allowance !== 'object') {\n hostsNotDeclared.push(name);\n continue;\n }\n if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_BASE_URL) continue;\n if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DEPLOYMENT_CONFIGURED) continue;\n // A host derived from another answer (#1937) is never asked. The answer it reads is KEPT when supplied, so a\n // connection that chose its cloud dials that cloud's host; unanswered, the allowance's own default applies.\n if (allowance.kind === ProviderOAuth2EndpointHostAllowanceKind.DERIVED_FROM_CONNECTION_ANSWER) {\n declared.add(allowance.answer);\n continue;\n }\n asked.push(name);\n }\n return { asked: asked.length === 0 ? undefined : asked, declared, hostsNotDeclared, templateDefective, positionsByName };\n}\n\n/** The REST contract slice {@link describeProviderAskedConnectionParameters} reads: the base URL, its allowances, the OAuth2 block. */\nexport interface ProviderConnectFormRestContract extends ProviderCredentialBaseUrlContract {\n readonly oauth2?: ProviderRestOAuth2;\n}\n\n/**\n * The connection parameters the connect screen ASKS for, for the connection whose REST contract this is: the OAuth2\n * flow's asked placeholders when the contract declares an OAuth2 block, else the placeholders a pasted credential's base\n * URL asks for (#1097). The catalogue answers `connectionParameters` with it, and the discovery contribution carries it\n * as `connectionParameterNames` so the labelling pipeline plans a word for each (#3251).\n *\n * Pass the CONNECTION's contract: for a member of a declared shared connection, the base's, whose client connects.\n */\nexport function describeProviderAskedConnectionParameters(contract: ProviderConnectFormRestContract | undefined): readonly string[] | undefined {\n if (contract === undefined) return undefined;\n return contract.oauth2 !== undefined\n ? describeProviderOAuth2AskedConnectionParameters(contract.oauth2)\n : describeProviderCredentialBaseUrlAnswers(contract).asked;\n}\n\n/** What {@link describeProviderConnectionParameterNames} reads of one protocol binding of a provider module. */\nexport interface ProviderConnectionParameterBindingFacts {\n readonly runtimeContract: unknown;\n}\n\n/**\n * The discovery contribution's `connectionParameterNames` (#3251): what the connect screen asks of a person connecting\n * the provider's OWN connection, sorted, or `undefined` when it asks nothing. Read from the module's REST binding (the\n * runtime contract of kind `ProviderProtocolRuntimeKind.REST`), the one the catalogue reads through\n * `getProviderRuntimeContract(ref, REST_API)`. Pure; never throws.\n *\n * Every provider producer derives it with this function rather than restating the names, so the words planned for the\n * screen are planned for the names it asks.\n */\nexport function describeProviderConnectionParameterNames(protocols: ReadonlyArray<ProviderConnectionParameterBindingFacts>): string[] | undefined {\n const contract = protocols\n .map((binding) => binding.runtimeContract)\n .find((candidate): candidate is ProviderConnectFormRestContract => candidate !== null && typeof candidate === 'object'\n && (candidate as { kind?: unknown }).kind === ProviderProtocolRuntimeKind.REST);\n const asked = describeProviderAskedConnectionParameters(contract);\n return asked === undefined ? undefined : [...new Set(asked)].sort((left, right) => left.localeCompare(right));\n}\n"]}
@@ -20,6 +20,12 @@ export interface ProviderOAuth2TokenEndpointHosts {
20
20
  readonly exact: readonly string[];
21
21
  /** Dotted host suffixes it may resolve to (`<labels><suffix>`), from a declared allowance. */
22
22
  readonly suffixes: readonly string[];
23
+ /**
24
+ * The most DNS labels before any of `suffixes` (#3640) — the allowance's `hostSuffixMaxLabels`, carried because the
25
+ * description comes from ONE allowance. Absent, unbounded. Without it two descriptions could be read as able to meet
26
+ * under nested suffixes that the bound keeps apart.
27
+ */
28
+ readonly suffixMaxLabels?: number;
23
29
  /**
24
30
  * `true` when the set cannot be known from the declaration — a host filled from the deployment
25
31
  * (`DEPLOYMENT_BASE_URL` / `DEPLOYMENT_CONFIGURED`), a partial-host template, a template defect, or a
@@ -1 +1 @@
1
- {"version":3,"file":"provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts","sourceRoot":"","sources":["../../../../src/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,sDAAsD,CAAC;AAE9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gCAAgC;IAC/C,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,wEAAwE;AACxE,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,wBAAwB,CAAC,GACtE,gCAAgC,CAiClC;AAeD;;;;GAIG;AACH,wBAAgB,yCAAyC,CACvD,IAAI,EAAE,gCAAgC,EACtC,KAAK,EAAE,gCAAgC,GACtC,OAAO,GAAG,SAAS,CAOrB"}
1
+ {"version":3,"file":"provider-oauth2-token-endpoint-hosts.external-connectors-models.d.ts","sourceRoot":"","sources":["../../../src/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,sDAAsD,CAAC;AAE9D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,gCAAgC;IAC/C,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,8FAA8F;IAC9F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED,wEAAwE;AACxE,wBAAgB,wCAAwC,CACtD,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,UAAU,GAAG,wBAAwB,CAAC,GACtE,gCAAgC,CAiClC;AAqBD;;;;GAIG;AACH,wBAAgB,yCAAyC,CACvD,IAAI,EAAE,gCAAgC,EACtC,KAAK,EAAE,gCAAgC,GACtC,OAAO,GAAG,SAAS,CAQrB"}
@@ -1,4 +1,4 @@
1
- import { classifyProviderOAuth2EndpointPlaceholders, findProviderOAuth2EndpointTemplateDefects, ProviderOAuth2EndpointHostAllowanceKind, ProviderOAuth2EndpointPlaceholderPosition, } from './rest-operations.external-connectors-models.schemas.js';
1
+ import { classifyProviderOAuth2EndpointPlaceholders, findProviderOAuth2EndpointTemplateDefects, providerHostIsUnderSuffix, providerHostSuffixesOverlap, ProviderOAuth2EndpointHostAllowanceKind, ProviderOAuth2EndpointPlaceholderPosition, } from './rest-operations.external-connectors-models.schemas.js';
2
2
  /** See {@link ProviderOAuth2TokenEndpointHosts}. Pure; never throws. */
3
3
  export function describeProviderOAuth2TokenEndpointHosts(oauth2) {
4
4
  const undeterminable = { exact: [], suffixes: [], undeterminable: true };
@@ -26,16 +26,21 @@ export function describeProviderOAuth2TokenEndpointHosts(oauth2) {
26
26
  return undeterminable;
27
27
  exact.push(host);
28
28
  }
29
- return { exact, suffixes: [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase()), undeterminable: false };
29
+ return { exact, ...declaredSuffixesOf(allowance), undeterminable: false };
30
30
  }
31
31
  if (!occurrence.occupiesWholeHost)
32
32
  return undeterminable;
33
33
  return {
34
34
  exact: allowance.values.map((value) => value.toLowerCase()),
35
- suffixes: [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase()),
35
+ ...declaredSuffixesOf(allowance),
36
36
  undeterminable: false,
37
37
  };
38
38
  }
39
+ /** The lower-case suffixes of a declared allowance, with its label bound when it declares one (#3640). */
40
+ function declaredSuffixesOf(allowance) {
41
+ const suffixes = [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase());
42
+ return suffixes.length === 0 || allowance.hostSuffixMaxLabels === undefined ? { suffixes } : { suffixes, suffixMaxLabels: allowance.hostSuffixMaxLabels };
43
+ }
39
44
  /**
40
45
  * The lower-case host of an absolute `http(s)://` string, without port — a string scan rather than a `URL`
41
46
  * parse, because this package carries no DOM or Node library types. Only called on a template
@@ -55,10 +60,11 @@ function literalHostOf(value) {
55
60
  * and disjoint, `undefined` when either side is undeterminable and no overlap was found.
56
61
  */
57
62
  export function providerOAuth2TokenEndpointHostsIntersect(left, right) {
58
- const underSuffix = (host, suffix) => host.endsWith(suffix) && host.length > suffix.length;
59
- const overlaps = left.exact.some((host) => right.exact.includes(host) || right.suffixes.some((suffix) => underSuffix(host, suffix)))
60
- || right.exact.some((host) => left.suffixes.some((suffix) => underSuffix(host, suffix)))
61
- || left.suffixes.some((suffix) => right.suffixes.some((other) => suffix.endsWith(other) || other.endsWith(suffix)));
63
+ // The one suffix test (#3640), so a label bound narrows the comparison exactly as it narrows an admitted answer.
64
+ const bounded = (hosts, suffix) => (hosts.suffixMaxLabels === undefined ? { suffix } : { suffix, maxLabels: hosts.suffixMaxLabels });
65
+ const overlaps = left.exact.some((host) => right.exact.includes(host) || right.suffixes.some((suffix) => providerHostIsUnderSuffix(host, suffix, right.suffixMaxLabels)))
66
+ || right.exact.some((host) => left.suffixes.some((suffix) => providerHostIsUnderSuffix(host, suffix, left.suffixMaxLabels)))
67
+ || left.suffixes.some((suffix) => right.suffixes.some((other) => providerHostSuffixesOverlap(bounded(left, suffix), bounded(right, other))));
62
68
  if (overlaps)
63
69
  return true;
64
70
  return left.undeterminable || right.undeterminable ? undefined : false;
@@ -1 +1 @@
1
- {"version":3,"file":"provider-oauth2-token-endpoint-hosts.external-connectors-models.js","sourceRoot":"","sources":["../../../../src/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n classifyProviderOAuth2EndpointPlaceholders,\n findProviderOAuth2EndpointTemplateDefects,\n ProviderOAuth2EndpointHostAllowanceKind,\n ProviderOAuth2EndpointPlaceholderPosition,\n type ProviderRestOAuth2,\n} from './rest-operations.external-connectors-models.schemas';\n\n/**\n * The hosts an OAuth2 TOKEN endpoint template can resolve to, derived from the template and its declared\n * host allowances — values-free, so it can travel in a companion contribution and be compared at\n * `wildo config sync` without loading the provider's module (#1725).\n *\n * ## Why the token endpoint, and why hosts\n *\n * A declared shared connection has ONE OAuth client, the base ref's. A member ref whose own catalogue entry\n * names a different AUTHORIZATION SERVER is not the same vendor grant at all — a refresh token Microsoft\n * issued means nothing to another server — so declaring the two into one connection is a mistake that must\n * be refused rather than discovered when the first refresh fails. The token endpoint is where a grant is\n * redeemed and renewed, and its host is what identifies the server that issued it.\n *\n * Sets, not strings, because a catalogue endpoint is often templated (`https://{cloud}/{tenantId}/…`) and\n * admits several login hosts; two refs agree on the authorization server when their sets can meet.\n */\nexport interface ProviderOAuth2TokenEndpointHosts {\n /** Exact lower-case hosts the token endpoint may resolve to. */\n readonly exact: readonly string[];\n /** Dotted host suffixes it may resolve to (`<labels><suffix>`), from a declared allowance. */\n readonly suffixes: readonly string[];\n /**\n * `true` when the set cannot be known from the declaration — a host filled from the deployment\n * (`DEPLOYMENT_BASE_URL` / `DEPLOYMENT_CONFIGURED`), a partial-host template, a template defect, or a\n * host placeholder with no allowance. A comparison involving an undeterminable side is answered\n * `undefined`, never guessed.\n */\n readonly undeterminable: boolean;\n}\n\n/** See {@link ProviderOAuth2TokenEndpointHosts}. Pure; never throws. */\nexport function describeProviderOAuth2TokenEndpointHosts(\n oauth2: Pick<ProviderRestOAuth2, 'tokenUrl' | 'endpointHostAllowances'>,\n): ProviderOAuth2TokenEndpointHosts {\n const undeterminable: ProviderOAuth2TokenEndpointHosts = { exact: [], suffixes: [], undeterminable: true };\n const template = oauth2.tokenUrl;\n if (typeof template !== 'string' || findProviderOAuth2EndpointTemplateDefects(template).length > 0) return undeterminable;\n\n const hostForming = classifyProviderOAuth2EndpointPlaceholders(template)\n .filter((occurrence) => occurrence.position !== ProviderOAuth2EndpointPlaceholderPosition.PATH_OR_QUERY);\n if (hostForming.length === 0) {\n // Path placeholders are still braces here; the host is literal, which is all this reads.\n const host = literalHostOf(template);\n return host === undefined ? undeterminable : { exact: [host], suffixes: [], undeterminable: false };\n }\n if (hostForming.length > 1) return undeterminable;\n\n const [occurrence] = hostForming;\n const allowance = oauth2.endpointHostAllowances?.[occurrence!.name];\n if (allowance === undefined || allowance.kind !== ProviderOAuth2EndpointHostAllowanceKind.DECLARED_VALUES) return undeterminable;\n\n if (occurrence!.position === ProviderOAuth2EndpointPlaceholderPosition.ORIGIN) {\n const exact: string[] = [];\n for (const value of allowance.values) {\n const host = literalHostOf(value);\n if (host === undefined) return undeterminable;\n exact.push(host);\n }\n return { exact, suffixes: [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase()), undeterminable: false };\n }\n if (!occurrence!.occupiesWholeHost) return undeterminable;\n return {\n exact: allowance.values.map((value) => value.toLowerCase()),\n suffixes: [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase()),\n undeterminable: false,\n };\n}\n\n/**\n * The lower-case host of an absolute `http(s)://` string, without port — a string scan rather than a `URL`\n * parse, because this package carries no DOM or Node library types. Only called on a template\n * `findProviderOAuth2EndpointTemplateDefects` already admitted (or a declared origin value), so the authority\n * has no userinfo or backslash to confuse the scan.\n */\nfunction literalHostOf(value: string): string | undefined {\n const match = /^https?:\\/\\/([^/?#]+)/i.exec(value);\n if (match === null) return undefined;\n const host = match[1]!.replace(/:\\d+$/, '').toLowerCase();\n return host.length === 0 || host.includes('{') || host.includes('@') ? undefined : host;\n}\n\n/**\n * Whether two token-endpoint host sets can name the same authorization server: `true` when they share a\n * host (or one's host falls under the other's suffix, or two suffixes nest), `false` when both are known\n * and disjoint, `undefined` when either side is undeterminable and no overlap was found.\n */\nexport function providerOAuth2TokenEndpointHostsIntersect(\n left: ProviderOAuth2TokenEndpointHosts,\n right: ProviderOAuth2TokenEndpointHosts,\n): boolean | undefined {\n const underSuffix = (host: string, suffix: string): boolean => host.endsWith(suffix) && host.length > suffix.length;\n const overlaps = left.exact.some((host) => right.exact.includes(host) || right.suffixes.some((suffix) => underSuffix(host, suffix)))\n || right.exact.some((host) => left.suffixes.some((suffix) => underSuffix(host, suffix)))\n || left.suffixes.some((suffix) => right.suffixes.some((other) => suffix.endsWith(other) || other.endsWith(suffix)));\n if (overlaps) return true;\n return left.undeterminable || right.undeterminable ? undefined : false;\n}\n"]}
1
+ {"version":3,"file":"provider-oauth2-token-endpoint-hosts.external-connectors-models.js","sourceRoot":"","sources":["../../../src/protocols/provider-oauth2-token-endpoint-hosts.external-connectors-models.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n classifyProviderOAuth2EndpointPlaceholders,\n findProviderOAuth2EndpointTemplateDefects,\n providerHostIsUnderSuffix,\n providerHostSuffixesOverlap,\n ProviderOAuth2EndpointHostAllowanceKind,\n ProviderOAuth2EndpointPlaceholderPosition,\n type ProviderRestOAuth2,\n} from './rest-operations.external-connectors-models.schemas';\n\n/**\n * The hosts an OAuth2 TOKEN endpoint template can resolve to, derived from the template and its declared\n * host allowances — values-free, so it can travel in a companion contribution and be compared at\n * `wildo config sync` without loading the provider's module (#1725).\n *\n * ## Why the token endpoint, and why hosts\n *\n * A declared shared connection has ONE OAuth client, the base ref's. A member ref whose own catalogue entry\n * names a different AUTHORIZATION SERVER is not the same vendor grant at all — a refresh token Microsoft\n * issued means nothing to another server — so declaring the two into one connection is a mistake that must\n * be refused rather than discovered when the first refresh fails. The token endpoint is where a grant is\n * redeemed and renewed, and its host is what identifies the server that issued it.\n *\n * Sets, not strings, because a catalogue endpoint is often templated (`https://{cloud}/{tenantId}/…`) and\n * admits several login hosts; two refs agree on the authorization server when their sets can meet.\n */\nexport interface ProviderOAuth2TokenEndpointHosts {\n /** Exact lower-case hosts the token endpoint may resolve to. */\n readonly exact: readonly string[];\n /** Dotted host suffixes it may resolve to (`<labels><suffix>`), from a declared allowance. */\n readonly suffixes: readonly string[];\n /**\n * The most DNS labels before any of `suffixes` (#3640) — the allowance's `hostSuffixMaxLabels`, carried because the\n * description comes from ONE allowance. Absent, unbounded. Without it two descriptions could be read as able to meet\n * under nested suffixes that the bound keeps apart.\n */\n readonly suffixMaxLabels?: number;\n /**\n * `true` when the set cannot be known from the declaration — a host filled from the deployment\n * (`DEPLOYMENT_BASE_URL` / `DEPLOYMENT_CONFIGURED`), a partial-host template, a template defect, or a\n * host placeholder with no allowance. A comparison involving an undeterminable side is answered\n * `undefined`, never guessed.\n */\n readonly undeterminable: boolean;\n}\n\n/** See {@link ProviderOAuth2TokenEndpointHosts}. Pure; never throws. */\nexport function describeProviderOAuth2TokenEndpointHosts(\n oauth2: Pick<ProviderRestOAuth2, 'tokenUrl' | 'endpointHostAllowances'>,\n): ProviderOAuth2TokenEndpointHosts {\n const undeterminable: ProviderOAuth2TokenEndpointHosts = { exact: [], suffixes: [], undeterminable: true };\n const template = oauth2.tokenUrl;\n if (typeof template !== 'string' || findProviderOAuth2EndpointTemplateDefects(template).length > 0) return undeterminable;\n\n const hostForming = classifyProviderOAuth2EndpointPlaceholders(template)\n .filter((occurrence) => occurrence.position !== ProviderOAuth2EndpointPlaceholderPosition.PATH_OR_QUERY);\n if (hostForming.length === 0) {\n // Path placeholders are still braces here; the host is literal, which is all this reads.\n const host = literalHostOf(template);\n return host === undefined ? undeterminable : { exact: [host], suffixes: [], undeterminable: false };\n }\n if (hostForming.length > 1) return undeterminable;\n\n const [occurrence] = hostForming;\n const allowance = oauth2.endpointHostAllowances?.[occurrence!.name];\n if (allowance === undefined || allowance.kind !== ProviderOAuth2EndpointHostAllowanceKind.DECLARED_VALUES) return undeterminable;\n\n if (occurrence!.position === ProviderOAuth2EndpointPlaceholderPosition.ORIGIN) {\n const exact: string[] = [];\n for (const value of allowance.values) {\n const host = literalHostOf(value);\n if (host === undefined) return undeterminable;\n exact.push(host);\n }\n return { exact, ...declaredSuffixesOf(allowance), undeterminable: false };\n }\n if (!occurrence!.occupiesWholeHost) return undeterminable;\n return {\n exact: allowance.values.map((value) => value.toLowerCase()),\n ...declaredSuffixesOf(allowance),\n undeterminable: false,\n };\n}\n\n/** The lower-case suffixes of a declared allowance, with its label bound when it declares one (#3640). */\nfunction declaredSuffixesOf(allowance: { readonly hostSuffixes?: readonly string[]; readonly hostSuffixMaxLabels?: number }): Pick<ProviderOAuth2TokenEndpointHosts, 'suffixes' | 'suffixMaxLabels'> {\n const suffixes = [...(allowance.hostSuffixes ?? [])].map((suffix) => suffix.toLowerCase());\n return suffixes.length === 0 || allowance.hostSuffixMaxLabels === undefined ? { suffixes } : { suffixes, suffixMaxLabels: allowance.hostSuffixMaxLabels };\n}\n\n/**\n * The lower-case host of an absolute `http(s)://` string, without port — a string scan rather than a `URL`\n * parse, because this package carries no DOM or Node library types. Only called on a template\n * `findProviderOAuth2EndpointTemplateDefects` already admitted (or a declared origin value), so the authority\n * has no userinfo or backslash to confuse the scan.\n */\nfunction literalHostOf(value: string): string | undefined {\n const match = /^https?:\\/\\/([^/?#]+)/i.exec(value);\n if (match === null) return undefined;\n const host = match[1]!.replace(/:\\d+$/, '').toLowerCase();\n return host.length === 0 || host.includes('{') || host.includes('@') ? undefined : host;\n}\n\n/**\n * Whether two token-endpoint host sets can name the same authorization server: `true` when they share a\n * host (or one's host falls under the other's suffix, or two suffixes nest), `false` when both are known\n * and disjoint, `undefined` when either side is undeterminable and no overlap was found.\n */\nexport function providerOAuth2TokenEndpointHostsIntersect(\n left: ProviderOAuth2TokenEndpointHosts,\n right: ProviderOAuth2TokenEndpointHosts,\n): boolean | undefined {\n // The one suffix test (#3640), so a label bound narrows the comparison exactly as it narrows an admitted answer.\n const bounded = (hosts: ProviderOAuth2TokenEndpointHosts, suffix: string) => (hosts.suffixMaxLabels === undefined ? { suffix } : { suffix, maxLabels: hosts.suffixMaxLabels });\n const overlaps = left.exact.some((host) => right.exact.includes(host) || right.suffixes.some((suffix) => providerHostIsUnderSuffix(host, suffix, right.suffixMaxLabels)))\n || right.exact.some((host) => left.suffixes.some((suffix) => providerHostIsUnderSuffix(host, suffix, left.suffixMaxLabels)))\n || left.suffixes.some((suffix) => right.suffixes.some((other) => providerHostSuffixesOverlap(bounded(left, suffix), bounded(right, other))));\n if (overlaps) return true;\n return left.undeterminable || right.undeterminable ? undefined : false;\n}\n"]}
@@ -0,0 +1,50 @@
1
+ import type { ExternalProvider_Connection_OwnerScope } from '../core/security.external-connectors-models.schemas';
2
+ /**
3
+ * The part of a vendor registration's contract a provider module reads AT LOAD (#3252, #2712), kept in the contracts
4
+ * package because a provider module may import only its contract packages at load (`check:provider-module-eager-graph`):
5
+ * its `./companion` entry derives its discovery contribution from the module synchronously, so whatever it calls runs
6
+ * in every process that discovers providers. The builder types, the door-side helpers and the package writer stay in
7
+ * `@wildo-ai/external-connectors-private`; a module reaches those only through `import type`, or through what a door
8
+ * hands its build.
9
+ */
10
+ /** The owners a vendor registration is built for: the application's own app, or an organization's. */
11
+ type VendorRegistrationOwner = ExternalProvider_Connection_OwnerScope.APPLICATION | ExternalProvider_Connection_OwnerScope.ORGANIZATION;
12
+ /** How a brand image is drawn for a vendor's package (#2712), named by a module's `vendorRegistration.brandImages`. */
13
+ export declare enum ProviderVendorRegistrationBrandImageRendering {
14
+ /** The rendition as the brand draws it, fitted inside the size on a transparent background. */
15
+ AS_DRAWN = "AS_DRAWN",
16
+ /**
17
+ * Every pixel white, keeping the rendition's transparency: a silhouette on a transparent background, what Teams
18
+ * requires of an app's outline icon. Drawn from a rendition whose shape is in its alpha channel (the monochrome symbol).
19
+ */
20
+ WHITE_ON_TRANSPARENT = "WHITE_ON_TRANSPARENT"
21
+ }
22
+ /** What {@link describeProviderVendorRegistrationSteps} reads of one declared step (`ProviderVendorRegistrationStepDeclaration`). */
23
+ export interface ProviderVendorRegistrationStepDeclarationFacts {
24
+ readonly text: string;
25
+ readonly params?: Readonly<Record<string, string>>;
26
+ readonly countParams?: readonly string[];
27
+ readonly ownerScopes: readonly VendorRegistrationOwner[];
28
+ }
29
+ /**
30
+ * A declared step as a discovery contribution carries it (#3252): values-free, for the labelling pipeline. Its arrays
31
+ * are mutable on purpose: the discovery schema's inferred type (`ProviderCompanionContribution['vendorRegistrationSteps']`,
32
+ * `@wildo-ai/saas-models`) refuses a readonly one, and a module assigns this straight into its contribution.
33
+ */
34
+ export interface ProviderVendorRegistrationStepDescription {
35
+ ref: string;
36
+ text: string;
37
+ params?: Record<string, string>;
38
+ countParams?: string[];
39
+ ownerScopes: VendorRegistrationOwner[];
40
+ }
41
+ /**
42
+ * The discovery contribution's `vendorRegistrationSteps` (#3252): every step the module declares, sorted by ref, or
43
+ * `undefined` for a module with no vendor registration. Every producer derives it with this function rather than
44
+ * restating the steps, so the words planned are planned for the steps a build can return.
45
+ */
46
+ export declare function describeProviderVendorRegistrationSteps(registration: {
47
+ readonly steps?: Readonly<Record<string, ProviderVendorRegistrationStepDeclarationFacts>>;
48
+ } | undefined): ProviderVendorRegistrationStepDescription[] | undefined;
49
+ export {};
50
+ //# sourceMappingURL=provider-vendor-registration.external-connectors-models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-vendor-registration.external-connectors-models.d.ts","sourceRoot":"","sources":["../../../src/protocols/provider-vendor-registration.external-connectors-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sCAAsC,EAAE,MAAM,qDAAqD,CAAC;AAElH;;;;;;;GAOG;AAEH,sGAAsG;AACtG,KAAK,uBAAuB,GAAG,sCAAsC,CAAC,WAAW,GAAG,sCAAsC,CAAC,YAAY,CAAC;AAExI,uHAAuH;AACvH,oBAAY,6CAA6C;IACvD,+FAA+F;IAC/F,QAAQ,aAAa;IACrB;;;OAGG;IACH,oBAAoB,yBAAyB;CAC9C;AAED,qIAAqI;AACrI,MAAM,WAAW,8CAA8C;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC1D;AAED;;;;GAIG;AACH,MAAM,WAAW,yCAAyC;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,uBAAuB,EAAE,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,uCAAuC,CACrD,YAAY,EAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,8CAA8C,CAAC,CAAC,CAAA;CAAE,GAAG,SAAS,GACtH,yCAAyC,EAAE,GAAG,SAAS,CAWzD"}
@@ -0,0 +1,30 @@
1
+ /** How a brand image is drawn for a vendor's package (#2712), named by a module's `vendorRegistration.brandImages`. */
2
+ export var ProviderVendorRegistrationBrandImageRendering;
3
+ (function (ProviderVendorRegistrationBrandImageRendering) {
4
+ /** The rendition as the brand draws it, fitted inside the size on a transparent background. */
5
+ ProviderVendorRegistrationBrandImageRendering["AS_DRAWN"] = "AS_DRAWN";
6
+ /**
7
+ * Every pixel white, keeping the rendition's transparency: a silhouette on a transparent background, what Teams
8
+ * requires of an app's outline icon. Drawn from a rendition whose shape is in its alpha channel (the monochrome symbol).
9
+ */
10
+ ProviderVendorRegistrationBrandImageRendering["WHITE_ON_TRANSPARENT"] = "WHITE_ON_TRANSPARENT";
11
+ })(ProviderVendorRegistrationBrandImageRendering || (ProviderVendorRegistrationBrandImageRendering = {}));
12
+ /**
13
+ * The discovery contribution's `vendorRegistrationSteps` (#3252): every step the module declares, sorted by ref, or
14
+ * `undefined` for a module with no vendor registration. Every producer derives it with this function rather than
15
+ * restating the steps, so the words planned are planned for the steps a build can return.
16
+ */
17
+ export function describeProviderVendorRegistrationSteps(registration) {
18
+ if (registration === undefined)
19
+ return undefined;
20
+ return Object.entries(registration.steps ?? {})
21
+ .sort(([left], [right]) => left.localeCompare(right))
22
+ .map(([ref, declaration]) => ({
23
+ ref,
24
+ text: declaration.text,
25
+ ...(declaration.params === undefined || Object.keys(declaration.params).length === 0 ? {} : { params: { ...declaration.params } }),
26
+ ...(declaration.countParams === undefined || declaration.countParams.length === 0 ? {} : { countParams: [...declaration.countParams] }),
27
+ ownerScopes: [...declaration.ownerScopes],
28
+ }));
29
+ }
30
+ //# sourceMappingURL=provider-vendor-registration.external-connectors-models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-vendor-registration.external-connectors-models.js","sourceRoot":"","sources":["../../../src/protocols/provider-vendor-registration.external-connectors-models.ts"],"names":[],"mappings":"AAcA,uHAAuH;AACvH,MAAM,CAAN,IAAY,6CAQX;AARD,WAAY,6CAA6C;IACvD,+FAA+F;IAC/F,sEAAqB,CAAA;IACrB;;;OAGG;IACH,8FAA6C,CAAA;AAC/C,CAAC,EARW,6CAA6C,KAA7C,6CAA6C,QAQxD;AAuBD;;;;GAIG;AACH,MAAM,UAAU,uCAAuC,CACrD,YAAuH;IAEvH,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,OAAO,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;SAC5C,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SACpD,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;QAC5B,GAAG;QACH,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,GAAG,CAAC,WAAW,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAClI,GAAG,CAAC,WAAW,CAAC,WAAW,KAAK,SAAS,IAAI,WAAW,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;QACvI,WAAW,EAAE,CAAC,GAAG,WAAW,CAAC,WAAW,CAAC;KAC1C,CAAC,CAAC,CAAC;AACR,CAAC","sourcesContent":["import type { ExternalProvider_Connection_OwnerScope } from '../core/security.external-connectors-models.schemas';\n\n/**\n * The part of a vendor registration's contract a provider module reads AT LOAD (#3252, #2712), kept in the contracts\n * package because a provider module may import only its contract packages at load (`check:provider-module-eager-graph`):\n * its `./companion` entry derives its discovery contribution from the module synchronously, so whatever it calls runs\n * in every process that discovers providers. The builder types, the door-side helpers and the package writer stay in\n * `@wildo-ai/external-connectors-private`; a module reaches those only through `import type`, or through what a door\n * hands its build.\n */\n\n/** The owners a vendor registration is built for: the application's own app, or an organization's. */\ntype VendorRegistrationOwner = ExternalProvider_Connection_OwnerScope.APPLICATION | ExternalProvider_Connection_OwnerScope.ORGANIZATION;\n\n/** How a brand image is drawn for a vendor's package (#2712), named by a module's `vendorRegistration.brandImages`. */\nexport enum ProviderVendorRegistrationBrandImageRendering {\n /** The rendition as the brand draws it, fitted inside the size on a transparent background. */\n AS_DRAWN = 'AS_DRAWN',\n /**\n * Every pixel white, keeping the rendition's transparency: a silhouette on a transparent background, what Teams\n * requires of an app's outline icon. Drawn from a rendition whose shape is in its alpha channel (the monochrome symbol).\n */\n WHITE_ON_TRANSPARENT = 'WHITE_ON_TRANSPARENT',\n}\n\n/** What {@link describeProviderVendorRegistrationSteps} reads of one declared step (`ProviderVendorRegistrationStepDeclaration`). */\nexport interface ProviderVendorRegistrationStepDeclarationFacts {\n readonly text: string;\n readonly params?: Readonly<Record<string, string>>;\n readonly countParams?: readonly string[];\n readonly ownerScopes: readonly VendorRegistrationOwner[];\n}\n\n/**\n * A declared step as a discovery contribution carries it (#3252): values-free, for the labelling pipeline. Its arrays\n * are mutable on purpose: the discovery schema's inferred type (`ProviderCompanionContribution['vendorRegistrationSteps']`,\n * `@wildo-ai/saas-models`) refuses a readonly one, and a module assigns this straight into its contribution.\n */\nexport interface ProviderVendorRegistrationStepDescription {\n ref: string;\n text: string;\n params?: Record<string, string>;\n countParams?: string[];\n ownerScopes: VendorRegistrationOwner[];\n}\n\n/**\n * The discovery contribution's `vendorRegistrationSteps` (#3252): every step the module declares, sorted by ref, or\n * `undefined` for a module with no vendor registration. Every producer derives it with this function rather than\n * restating the steps, so the words planned are planned for the steps a build can return.\n */\nexport function describeProviderVendorRegistrationSteps(\n registration: { readonly steps?: Readonly<Record<string, ProviderVendorRegistrationStepDeclarationFacts>> } | undefined,\n): ProviderVendorRegistrationStepDescription[] | undefined {\n if (registration === undefined) return undefined;\n return Object.entries(registration.steps ?? {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([ref, declaration]) => ({\n ref,\n text: declaration.text,\n ...(declaration.params === undefined || Object.keys(declaration.params).length === 0 ? {} : { params: { ...declaration.params } }),\n ...(declaration.countParams === undefined || declaration.countParams.length === 0 ? {} : { countParams: [...declaration.countParams] }),\n ownerScopes: [...declaration.ownerScopes],\n }));\n}\n"]}