@eduwork/dsh-oidc 0.2.3 → 0.3.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.en.md +6 -38
  2. package/CHANGELOG.md +7 -39
  3. package/CODE_OF_CONDUCT.en.md +1 -1
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/CONTRIBUTING.en.md +1 -1
  6. package/CONTRIBUTING.md +1 -1
  7. package/README.md +21 -130
  8. package/README_EN.md +36 -0
  9. package/SECURITY.en.md +1 -1
  10. package/SECURITY.md +1 -1
  11. package/SUPPORT.en.md +1 -1
  12. package/SUPPORT.md +1 -1
  13. package/docs/EDUWORK-MIGRATION.en.md +3 -31
  14. package/docs/EDUWORK-MIGRATION.md +3 -31
  15. package/docs/account-extensions.en.md +6 -6
  16. package/docs/account-extensions.md +3 -3
  17. package/docs/architecture.en.md +12 -117
  18. package/docs/architecture.md +12 -118
  19. package/docs/compatibility.en.md +6 -62
  20. package/docs/compatibility.md +6 -62
  21. package/docs/decisions/0001-one-plugin-composition-boundary.en.md +2 -2
  22. package/docs/decisions/0001-one-plugin-composition-boundary.md +2 -2
  23. package/docs/desktop-host.en.md +54 -55
  24. package/docs/desktop-host.md +63 -64
  25. package/docs/development.en.md +44 -44
  26. package/docs/development.md +6 -6
  27. package/docs/dsh-integration.en.md +13 -48
  28. package/docs/dsh-integration.md +14 -49
  29. package/docs/ecnu-reference.en.md +4 -61
  30. package/docs/ecnu-reference.md +4 -61
  31. package/docs/enterprise-profile.en.md +10 -31
  32. package/docs/enterprise-profile.md +11 -32
  33. package/docs/gateway-auth/README.md +168 -0
  34. package/docs/gateway-auth/README_EN.md +70 -0
  35. package/docs/gateway-auth/experimental-oidc-llm.en.md +53 -0
  36. package/docs/gateway-auth/experimental-oidc-llm.md +53 -0
  37. package/docs/gateway-auth/litellm-setup.en.md +114 -0
  38. package/docs/gateway-auth/litellm-setup.md +114 -0
  39. package/docs/gateway-auth/oidc-llm-draft.en.md +141 -0
  40. package/docs/gateway-auth/oidc-llm-draft.md +141 -0
  41. package/docs/getting-started.en.md +17 -122
  42. package/docs/getting-started.md +16 -225
  43. package/docs/key-binding-protocol.en.md +10 -220
  44. package/docs/key-binding-protocol.md +10 -220
  45. package/docs/oidc-interoperability.en.md +1 -1
  46. package/docs/oidc-interoperability.md +1 -1
  47. package/docs/open-integration.en.md +11 -0
  48. package/docs/open-integration.md +11 -0
  49. package/docs/public-resource-protocol.en.md +8 -44
  50. package/docs/public-resource-protocol.md +8 -43
  51. package/docs/release-checklist.en.md +7 -61
  52. package/docs/release-checklist.md +7 -61
  53. package/docs/security-model.en.md +10 -132
  54. package/docs/security-model.md +10 -132
  55. package/docs/server-integration-contract.en.md +12 -811
  56. package/docs/server-integration-contract.md +12 -823
  57. package/examples/ecnu.enterprise-profile.example.json +14 -19
  58. package/examples/enterprise-profile.example.json +73 -78
  59. package/examples/identity-only.example.json +1 -1
  60. package/examples/litellm.enterprise-profile.example.json +9 -0
  61. package/examples/oidc-llm.enterprise-profile.example.json +12 -0
  62. package/examples/resources-discovery.example.json +6 -9
  63. package/lib/callback-page.js +5 -5
  64. package/lib/client.js +31 -48
  65. package/lib/desktop-oidc.js +7 -11
  66. package/lib/gateway-backend.js +443 -0
  67. package/lib/gateway-protocol.js +6 -0
  68. package/lib/index.js +14 -15
  69. package/lib/litellm-protocol.js +117 -0
  70. package/lib/model-resource-transport.js +19 -0
  71. package/lib/oidc-llm-protocol.js +88 -0
  72. package/lib/oidc.js +37 -323
  73. package/lib/profile.js +34 -40
  74. package/lib/provider/authorization-scope.js +46 -0
  75. package/lib/provider/index.js +11 -2
  76. package/lib/provider/transforms.js +0 -1
  77. package/lib/typert-schemas.js +1 -1
  78. package/lib/typert.host.js +38 -38
  79. package/lib/typert.remote-client.js +37 -37
  80. package/package.json +7 -6
  81. package/protocol/openapi.yaml +33 -240
  82. package/protocol/resources.openapi.yaml +8 -9
  83. package/schema/enterprise-profile.v1alpha1.schema.json +595 -193
  84. package/README.en.md +0 -186
package/lib/profile.js CHANGED
@@ -1,10 +1,8 @@
1
1
  import { readFileSync } from 'node:fs'
2
2
 
3
3
  export const PROFILE_SCHEMA_VERSION = 'dsh-oidc/v1alpha1'
4
- export const DEFAULT_CREDENTIAL_REF = 'EDUWORK_API_KEY'
5
4
  const MAX_PROFILE_BYTES = 512 * 1024
6
5
  const idPattern = /^[a-z][a-z0-9-]{0,63}$/
7
- const credentialPattern = /^[A-Za-z_][A-Za-z0-9_]*$/
8
6
  const colorPattern = /^#[0-9a-fA-F]{6}$/
9
7
  const allowedModalities = new Set(['text', 'image'])
10
8
  const allowedThinkingLevels = new Set(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'])
@@ -15,10 +13,9 @@ const allowedThinkingFormats = new Set([
15
13
  ])
16
14
  const allowedRootKeys = new Set([
17
15
  'schemaVersion', 'id', 'displayName', 'organization', 'nativeInstitutionID',
18
- 'allowInsecureDevelopment', 'insecureDevelopmentOrigin', 'brand', 'oidc', 'keyBinding', 'provider',
16
+ 'allowInsecureDevelopment', 'insecureDevelopmentOrigin', 'brand', 'oidc', 'auth', 'provider',
19
17
  ])
20
18
  const allowedOidcKeys = new Set(['issuer', 'clientId', 'scopes'])
21
- const allowedKeyBindingKeys = new Set(['type', 'baseURL', 'credentialRef'])
22
19
  const allowedBrandKeys = new Set([
23
20
  'productName', 'organizationName', 'mark', 'logoURL', 'primaryColor',
24
21
  'loginTitle', 'loginDescription', 'supportURL',
@@ -217,9 +214,6 @@ export function normalizeModels(models, providerID) {
217
214
  }))
218
215
  }
219
216
 
220
- export function legacyCredentialRefs(profile) {
221
- return [...new Set([profile.id, profile.provider?.id].filter(Boolean).map(id => `${id.toUpperCase().replace(/[^A-Z0-9]/g, '_')}_API_KEY`))]
222
- }
223
217
 
224
218
  function normalizeRetryPolicy(value) {
225
219
  const source = object(value, 'profile.provider.retryPolicy')
@@ -281,35 +275,41 @@ export function normalizeEnterpriseProfile(raw) {
281
275
  if (allowedInsecureOrigin !== undefined && !allowInsecureDevelopment) {
282
276
  throw new Error('profile.insecureDevelopmentOrigin requires allowInsecureDevelopment=true')
283
277
  }
284
- const oidc = object(source.oidc, 'profile.oidc')
285
- const identityOnly = source.keyBinding === undefined && source.provider === undefined
286
- if (!identityOnly && (source.keyBinding === undefined || source.provider === undefined)) {
287
- throw new Error('profile.keyBinding and profile.provider must either both be present or both be omitted')
278
+ const gateway = source.auth !== undefined
279
+ if (gateway && source.oidc !== undefined) throw new Error('profile.auth cannot be combined with oidc')
280
+ let auth
281
+ if (gateway) {
282
+ const rawAuth = object(source.auth, 'profile.auth')
283
+ exactKeys(rawAuth, new Set(['discoveryUrl', 'expectedIssuer', 'experimentalOidcLlm', 'clientId', 'identityMode']), 'profile.auth')
284
+ const experimental = rawAuth.experimentalOidcLlm === true
285
+ if (rawAuth.experimentalOidcLlm !== undefined && typeof rawAuth.experimentalOidcLlm !== 'boolean') throw new Error('profile.auth.experimentalOidcLlm must be boolean')
286
+ if (!experimental && (rawAuth.clientId !== undefined || rawAuth.identityMode !== undefined)) throw new Error('profile.auth clientId and identityMode require experimentalOidcLlm=true')
287
+ if (experimental && !['oauth', 'oidc'].includes(rawAuth.identityMode)) throw new Error('profile.auth.identityMode must explicitly select oauth or oidc')
288
+ if (experimental && allowedInsecureOrigin && !rawAuth.expectedIssuer) throw new Error('development oidc-llm requires expectedIssuer')
289
+ const developmentOrigin = experimental ? allowedInsecureOrigin : undefined
290
+ auth = Object.freeze({
291
+ discoveryUrl: issuerURL(rawAuth.discoveryUrl, 'profile.auth.discoveryUrl', allowInsecureDevelopment, developmentOrigin),
292
+ ...(rawAuth.expectedIssuer === undefined ? {} : { expectedIssuer: issuerURL(rawAuth.expectedIssuer, 'profile.auth.expectedIssuer', allowInsecureDevelopment, developmentOrigin) }),
293
+ ...(experimental ? { experimentalOidcLlm: true, clientId: text(rawAuth.clientId, 'profile.auth.clientId', 256), identityMode: rawAuth.identityMode } : {}),
294
+ })
295
+ if (source.provider?.baseURL !== undefined) throw new Error('profile.auth derives provider.baseURL from validated discovery')
296
+ if (source.provider?.modelSource !== undefined && source.provider.modelSource !== 'discovery') throw new Error('profile.auth requires discovery modelSource')
288
297
  }
289
- const keyBinding = identityOnly ? {} : object(source.keyBinding, 'profile.keyBinding')
290
- const provider = identityOnly ? {} : object(source.provider, 'profile.provider')
298
+ const oidc = gateway ? {} : object(source.oidc, 'profile.oidc')
299
+ const identityOnly = !gateway
300
+ if (identityOnly && source.provider !== undefined) throw new Error('OIDC identity profiles cannot configure model resources; use auth.discoveryUrl for Access Token model access')
301
+ const provider = gateway ? { id, adapter: 'openai-compatible', ...object(source.provider ?? {}, 'profile.provider'), modelSource: 'discovery' } : {}
291
302
  exactKeys(oidc, allowedOidcKeys, 'profile.oidc')
292
- exactKeys(keyBinding, allowedKeyBindingKeys, 'profile.keyBinding')
293
303
  exactKeys(provider, allowedProviderKeys, 'profile.provider')
294
304
  const providerID = identityOnly ? id : text(provider.id, 'profile.provider.id', 64)
295
305
  if (!idPattern.test(providerID)) throw new Error('profile.provider.id is invalid')
296
- let credentialRef = keyBinding.credentialRef === undefined
297
- ? DEFAULT_CREDENTIAL_REF
298
- : text(keyBinding.credentialRef, 'profile.keyBinding.credentialRef', 128)
299
- if (!credentialPattern.test(credentialRef)) {
300
- throw new Error('profile.keyBinding.credentialRef must be a valid DSH credential reference')
301
- }
302
- if (legacyCredentialRefs({ id, provider: { id: providerID } }).includes(credentialRef)) credentialRef = DEFAULT_CREDENTIAL_REF
303
306
  if (!identityOnly && provider.adapter !== 'openai-compatible') throw new Error(`unsupported provider adapter ${String(provider.adapter)}`)
304
- const protocol = keyBinding.type ?? 'worker-user-center-v1'
305
- if (!['worker-user-center-v1', 'eduwork-resources-v1'].includes(protocol)) throw new Error('profile.keyBinding.type is not supported')
306
- const modelSource = provider.modelSource ?? 'profile'
307
- if (!['profile', 'discovery'].includes(modelSource)) throw new Error('profile.provider.modelSource must be profile or discovery')
307
+ const modelSource = 'discovery'
308
308
  const scopes = oidc.scopes
309
- if (!Array.isArray(scopes) || scopes.length < 2 || scopes.length > 64 || !scopes.includes('openid') || !scopes.includes('profile') || scopes.some(scope => typeof scope !== 'string' || scope.length > 128 || scope.trim() !== scope || scope === '' || /\s/.test(scope))) {
309
+ if (!gateway && (!Array.isArray(scopes) || scopes.length < 2 || scopes.length > 64 || !scopes.includes('openid') || !scopes.includes('profile') || scopes.some(scope => typeof scope !== 'string' || scope.length > 128 || scope.trim() !== scope || scope === '' || /\s/.test(scope)))) {
310
310
  throw new Error('profile.oidc.scopes must contain openid and profile; every scope must be a non-empty token')
311
311
  }
312
- if (new Set(scopes).size !== scopes.length) throw new Error('profile.oidc.scopes contains duplicates')
312
+ if (!gateway && new Set(scopes).size !== scopes.length) throw new Error('profile.oidc.scopes contains duplicates')
313
313
  return Object.freeze({
314
314
  schemaVersion: PROFILE_SCHEMA_VERSION,
315
315
  id,
@@ -319,22 +319,16 @@ export function normalizeEnterpriseProfile(raw) {
319
319
  ...(allowedInsecureOrigin === undefined ? {} : { insecureDevelopmentOrigin: allowedInsecureOrigin }),
320
320
  nativeInstitutionID: source.nativeInstitutionID === undefined ? id : text(source.nativeInstitutionID, 'profile.nativeInstitutionID', 64),
321
321
  brand: normalizeBrand(source.brand),
322
- oidc: Object.freeze({
322
+ ...(gateway ? { auth } : { oidc: Object.freeze({
323
323
  issuer: issuerURL(oidc.issuer, 'profile.oidc.issuer', allowInsecureDevelopment, allowedInsecureOrigin),
324
324
  clientId: text(oidc.clientId, 'profile.oidc.clientId', 256),
325
325
  scopes: Object.freeze([...scopes]),
326
- }),
327
- ...(identityOnly ? {} : { keyBinding: Object.freeze({
328
- type: protocol,
329
- baseURL: exactURL(keyBinding.baseURL, 'profile.keyBinding.baseURL', allowInsecureDevelopment, allowedInsecureOrigin),
330
- providerId: providerID,
331
- credentialRef,
332
- }),
333
- provider: Object.freeze({
326
+ }) }),
327
+ ...(identityOnly ? {} : { provider: Object.freeze({
334
328
  id: providerID,
335
329
  displayName: text(provider.displayName ?? source.displayName, 'profile.provider.displayName', 120),
336
330
  adapter: provider.adapter,
337
- baseURL: exactURL(provider.baseURL, 'profile.provider.baseURL', allowInsecureDevelopment, allowedInsecureOrigin),
331
+ baseURL: '',
338
332
  reasoning: provider.reasoning === undefined
339
333
  ? 'high'
340
334
  : (() => {
@@ -385,9 +379,9 @@ export function loadEnterpriseProfiles(raw = {}, environment = process.env) {
385
379
 
386
380
  export function enterpriseProviderConfig(profiles) {
387
381
  return {
388
- providers: Object.fromEntries([...profiles.values()].filter(profile => profile.provider?.models.length).map(profile => [profile.provider.id, {
382
+ providers: Object.fromEntries([...profiles.values()].filter(profile => profile.provider?.baseURL && profile.provider.models.length).map(profile => [profile.provider.id, {
389
383
  displayName: profile.provider.displayName,
390
- apiKeyEnv: profile.keyBinding.credentialRef,
384
+ apiKeyEnv: `DSH_GATEWAY_${profile.id.toUpperCase().replace(/-/g, '_')}_ACCESS`,
391
385
  baseURL: profile.provider.baseURL,
392
386
  allowInsecureDevelopment: profile.allowInsecureDevelopment,
393
387
  ...(profile.insecureDevelopmentOrigin === undefined ? {} : { insecureDevelopmentOrigin: profile.insecureDevelopmentOrigin }),
@@ -418,7 +412,7 @@ export function publicProfile(profile) {
418
412
  displayName: profile.displayName,
419
413
  organization: profile.organization,
420
414
  brand: profile.brand,
421
- credentialRef: profile.keyBinding?.credentialRef ?? '',
415
+ credentialRef: '',
422
416
  ...(profile.provider ? { provider: {
423
417
  id: profile.provider.id,
424
418
  displayName: profile.provider.displayName,
@@ -0,0 +1,46 @@
1
+ /** Keep prepared calls, credential resolution and streamed results in one authorization. */
2
+ export class AuthorizationScopedAdapter {
3
+ constructor(inner, storage, createScope) {
4
+ this.inner = inner
5
+ this.storage = storage
6
+ this.createScope = createScope
7
+ }
8
+
9
+ providerInfo(provider) { return this.inner.providerInfo(provider) }
10
+ providerRetryPolicy(provider) { return this.inner.providerRetryPolicy(provider) }
11
+ imageRequestPricing(provider, model) { return this.inner.imageRequestPricing(provider, model) }
12
+ listModels(provider) { return this.inner.listModels(provider) }
13
+ resolveModel(provider, model, signal) { return this.inner.resolveModel(provider, model, signal) }
14
+
15
+ async prepareCall(provider, model, signal) {
16
+ const scope = await this.createScope(provider)
17
+ const prepared = await this.inner.prepareCall(provider, model, signal)
18
+ return { model: prepared.model, stream: options => this.streamPrepared(prepared, options, scope) }
19
+ }
20
+
21
+ async * streamPrepared(prepared, options, scope) {
22
+ if (!scope) { yield* prepared.stream(options); return }
23
+ const lease = scope.open(options.signal)
24
+ let iterator
25
+ try {
26
+ lease.assertCurrent()
27
+ iterator = prepared.stream({ ...options, signal: lease.signal })[Symbol.asyncIterator]()
28
+ for (;;) {
29
+ lease.assertCurrent()
30
+ const next = await this.storage.run(lease, () => iterator.next())
31
+ // Even a transport that buffers or ignores abort must not emit stale data.
32
+ lease.assertCurrent()
33
+ if (next.done) return
34
+ yield next.value
35
+ }
36
+ } finally {
37
+ try { await this.storage.run(lease, () => iterator?.return?.()) }
38
+ finally { lease.close() }
39
+ }
40
+ }
41
+
42
+ async * stream(options) {
43
+ const prepared = await this.prepareCall(options.provider, options.model, options.signal)
44
+ yield* prepared.stream(options)
45
+ }
46
+ }
@@ -1,3 +1,4 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
1
2
  import { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'
2
3
  import { LlmError, assertUsableApiKey, resolveImageAttachmentAccess, resolveRetryPolicy } from '@deepseek-ai/dsh-llm'
3
4
  import { Config as PiAiConfig, PiAiAdapter } from '@deepseek-ai/dsh-llm-pi-ai'
@@ -10,6 +11,7 @@ import {
10
11
  } from './core.js'
11
12
  import { TransformingEnterpriseAdapter } from './transform-adapter.js'
12
13
  import { EnterpriseModelTransforms } from './transforms.js'
14
+ import { AuthorizationScopedAdapter } from './authorization-scope.js'
13
15
 
14
16
  export const name = 'dsh-oidc-provider'
15
17
  export const inject = ['llm']
@@ -108,6 +110,7 @@ export function resolveEnterpriseImageAccess(ctx, attachments, ref) {
108
110
  }
109
111
 
110
112
  export function apply(ctx, rawConfig = {}) {
113
+ const callAuthorization = new AsyncLocalStorage()
111
114
  const transforms = new EnterpriseModelTransforms(ctx)
112
115
  let current = () => settingsBase(rawConfig)
113
116
  let profiles = profilesFrom(current())
@@ -121,7 +124,10 @@ export function apply(ctx, rawConfig = {}) {
121
124
  }
122
125
  const ref = profile.apiKeyEnv
123
126
  const credentials = ctx.get('credentials')
124
- const hit = typeof rawConfig.resolveCredential === 'function'
127
+ const lease = callAuthorization.getStore()
128
+ const hit = lease
129
+ ? (await lease.resolveCredential(provider))?.value
130
+ : typeof rawConfig.resolveCredential === 'function'
125
131
  ? (await rawConfig.resolveCredential(provider))?.value
126
132
  : credentials === undefined
127
133
  ? launchEnvironmentOf(ctx).get(ref)?.value
@@ -133,9 +139,12 @@ export function apply(ctx, rawConfig = {}) {
133
139
  resolveImageAccess: (attachments, ref) => resolveEnterpriseImageAccess(ctx, attachments, ref),
134
140
  })
135
141
 
136
- const adapter = new TransformingEnterpriseAdapter(baseAdapter, transforms, (provider, model) => (
142
+ const transforming = new TransformingEnterpriseAdapter(baseAdapter, transforms, (provider, model) => (
137
143
  profiles.get(provider)?.modelPolicies.get(model) ?? { reasoning: true, supportsReasoningEffort: true }
138
144
  ))
145
+ const adapter = typeof rawConfig.createAuthorizationScope === 'function'
146
+ ? new AuthorizationScopedAdapter(transforming, callAuthorization, rawConfig.createAuthorizationScope)
147
+ : transforming
139
148
  let registration
140
149
  let directory
141
150
  const replaceProfiles = next => {
@@ -56,4 +56,3 @@ export class EnterpriseModelTransforms extends Service {
56
56
  return transformed
57
57
  }
58
58
  }
59
-
@@ -3,7 +3,7 @@ import { z } from 'zod'
3
3
  const pkg = '@eduwork/dsh-oidc'
4
4
  export const profileIdSchema = z.string().min(1).max(64)
5
5
  export const loginIdSchema = z.string().regex(/^[A-Za-z0-9_-]{32}$/)
6
- export const reconcileOptionsSchema = z.object({ allowProvision: z.boolean().optional() }).strict()
6
+ export const reconcileOptionsSchema = z.object({}).strict()
7
7
  export const baseURLSchema = z.string().min(1).max(2048)
8
8
  export const modelCatalogModeSchema = z.enum(['discovery', 'manual'])
9
9
  export const configurationTargetSchema = z.enum(['config', 'examples'])
@@ -1,44 +1,44 @@
1
- import {
1
+ import {
2
2
  accountResult, baseURLSchema, beginResult, configurationResult, configurationTargetSchema, openConfigurationResult, jsonParameter, managementResult, loginIdSchema, loginResult,
3
3
  modelCatalogModeSchema, profileIdSchema, reconcileOptionsSchema, restartResult, runtimeModelsSchema, resourcesResult, enterpriseSelectionResult, enterpriseSelectionOptionsSchema,
4
- } from './typert-schemas.js'
5
-
6
- const pkg = '@eduwork/dsh-oidc'
7
- const source = { file: 'lib/index.js', line: 1, column: 1 }
8
- const profile = () => jsonParameter('profileID', profileIdSchema, `${pkg}#ProfileID`)
9
- const login = () => jsonParameter('loginID', loginIdSchema, `${pkg}#LoginID`)
10
- const options = () => jsonParameter('options', reconcileOptionsSchema, `${pkg}#ReconcileOptions`)
11
- const baseURL = () => jsonParameter('baseURL', baseURLSchema, `${pkg}#BaseURL`)
12
- const modelMode = () => jsonParameter('modelMode', modelCatalogModeSchema, `${pkg}#ModelCatalogMode`)
13
- const models = () => jsonParameter('models', runtimeModelsSchema, `${pkg}#RuntimeModels`)
14
- const descriptor = (method, parameters, result) => ({
15
- id: `${pkg}#oidcAccounts/${method}`, service: 'oidcAccounts', namespace: 'oidcAccounts', method,
16
- invocation: { kind: 'direct' }, parameters, result, sourceLocation: source,
17
- })
18
-
19
- export const TYPERT = {
20
- package: pkg, face: 'host', schemas: [],
21
- invocations: [
4
+ } from './typert-schemas.js'
5
+
6
+ const pkg = '@eduwork/dsh-oidc'
7
+ const source = { file: 'lib/index.js', line: 1, column: 1 }
8
+ const profile = () => jsonParameter('profileID', profileIdSchema, `${pkg}#ProfileID`)
9
+ const login = () => jsonParameter('loginID', loginIdSchema, `${pkg}#LoginID`)
10
+ const options = () => jsonParameter('options', reconcileOptionsSchema, `${pkg}#ReconcileOptions`)
11
+ const baseURL = () => jsonParameter('baseURL', baseURLSchema, `${pkg}#BaseURL`)
12
+ const modelMode = () => jsonParameter('modelMode', modelCatalogModeSchema, `${pkg}#ModelCatalogMode`)
13
+ const models = () => jsonParameter('models', runtimeModelsSchema, `${pkg}#RuntimeModels`)
14
+ const descriptor = (method, parameters, result) => ({
15
+ id: `${pkg}#oidcAccounts/${method}`, service: 'oidcAccounts', namespace: 'oidcAccounts', method,
16
+ invocation: { kind: 'direct' }, parameters, result, sourceLocation: source,
17
+ })
18
+
19
+ export const TYPERT = {
20
+ package: pkg, face: 'host', schemas: [],
21
+ invocations: [
22
22
  descriptor('configuration', [], configurationResult),
23
23
  descriptor('openConfiguration', [jsonParameter('target', configurationTargetSchema, `${pkg}#ConfigurationTarget`)], openConfigurationResult),
24
- descriptor('status', [profile()], accountResult),
25
- descriptor('resources', [profile()], resourcesResult),
26
- descriptor('begin', [profile()], beginResult),
27
- descriptor('loginStatus', [login()], loginResult),
28
- descriptor('cancelLogin', [login()], loginResult),
24
+ descriptor('status', [profile()], accountResult),
25
+ descriptor('resources', [profile()], resourcesResult),
26
+ descriptor('begin', [profile()], beginResult),
27
+ descriptor('loginStatus', [login()], loginResult),
28
+ descriptor('cancelLogin', [login()], loginResult),
29
29
  descriptor('reconcile', [profile(), options()], accountResult),
30
30
  descriptor('selectEnterpriseModel', [profile(), jsonParameter('options', enterpriseSelectionOptionsSchema, `${pkg}#EnterpriseSelectionOptions`)], enterpriseSelectionResult),
31
- descriptor('logout', [profile()], accountResult),
32
- descriptor('management', [], managementResult),
33
- descriptor('activate', [profile()], managementResult),
34
- descriptor('configure', [profile()], managementResult),
35
- descriptor('addCustom', [baseURL()], managementResult),
36
- descriptor('updateCustom', [profile(), baseURL()], managementResult),
37
- descriptor('removeProfile', [profile()], managementResult),
38
- descriptor('configureModels', [profile(), modelMode(), models()], managementResult),
39
- descriptor('restart', [], restartResult),
40
- ],
41
- model: { services: [], events: [], objects: [] },
42
- }
43
-
44
- export default TYPERT
31
+ descriptor('logout', [profile()], accountResult),
32
+ descriptor('management', [], managementResult),
33
+ descriptor('activate', [profile()], managementResult),
34
+ descriptor('configure', [profile()], managementResult),
35
+ descriptor('addCustom', [baseURL()], managementResult),
36
+ descriptor('updateCustom', [profile(), baseURL()], managementResult),
37
+ descriptor('removeProfile', [profile()], managementResult),
38
+ descriptor('configureModels', [profile(), modelMode(), models()], managementResult),
39
+ descriptor('restart', [], restartResult),
40
+ ],
41
+ model: { services: [], events: [], objects: [] },
42
+ }
43
+
44
+ export default TYPERT
@@ -1,43 +1,43 @@
1
- import {
1
+ import {
2
2
  accountResult, baseURLSchema, beginResult, configurationResult, configurationTargetSchema, openConfigurationResult, jsonParameter, managementResult, loginIdSchema, loginResult,
3
3
  modelCatalogModeSchema, profileIdSchema, reconcileOptionsSchema, restartResult, runtimeModelsSchema, resourcesResult, enterpriseSelectionResult, enterpriseSelectionOptionsSchema,
4
- } from './typert-schemas.js'
5
-
6
- const pkg = '@eduwork/dsh-oidc'
7
- const source = { file: 'lib/index.js', line: 1, column: 1 }
8
- const profile = () => jsonParameter('profileID', profileIdSchema, `${pkg}#ProfileID`)
9
- const login = () => jsonParameter('loginID', loginIdSchema, `${pkg}#LoginID`)
10
- const options = () => jsonParameter('options', reconcileOptionsSchema, `${pkg}#ReconcileOptions`)
11
- const baseURL = () => jsonParameter('baseURL', baseURLSchema, `${pkg}#BaseURL`)
12
- const modelMode = () => jsonParameter('modelMode', modelCatalogModeSchema, `${pkg}#ModelCatalogMode`)
13
- const models = () => jsonParameter('models', runtimeModelsSchema, `${pkg}#RuntimeModels`)
14
- const descriptor = (method, parameters, result) => ({
15
- id: `${pkg}#oidcAccounts/${method}`, service: 'oidcAccounts', namespace: 'oidcAccounts', method,
16
- invocation: { kind: 'direct' }, parameters, result, sourceLocation: source,
17
- })
18
-
19
- export const TYPERT_REMOTE = {
20
- package: pkg,
21
- descriptors: [
4
+ } from './typert-schemas.js'
5
+
6
+ const pkg = '@eduwork/dsh-oidc'
7
+ const source = { file: 'lib/index.js', line: 1, column: 1 }
8
+ const profile = () => jsonParameter('profileID', profileIdSchema, `${pkg}#ProfileID`)
9
+ const login = () => jsonParameter('loginID', loginIdSchema, `${pkg}#LoginID`)
10
+ const options = () => jsonParameter('options', reconcileOptionsSchema, `${pkg}#ReconcileOptions`)
11
+ const baseURL = () => jsonParameter('baseURL', baseURLSchema, `${pkg}#BaseURL`)
12
+ const modelMode = () => jsonParameter('modelMode', modelCatalogModeSchema, `${pkg}#ModelCatalogMode`)
13
+ const models = () => jsonParameter('models', runtimeModelsSchema, `${pkg}#RuntimeModels`)
14
+ const descriptor = (method, parameters, result) => ({
15
+ id: `${pkg}#oidcAccounts/${method}`, service: 'oidcAccounts', namespace: 'oidcAccounts', method,
16
+ invocation: { kind: 'direct' }, parameters, result, sourceLocation: source,
17
+ })
18
+
19
+ export const TYPERT_REMOTE = {
20
+ package: pkg,
21
+ descriptors: [
22
22
  descriptor('configuration', [], configurationResult),
23
23
  descriptor('openConfiguration', [jsonParameter('target', configurationTargetSchema, `${pkg}#ConfigurationTarget`)], openConfigurationResult),
24
- descriptor('status', [profile()], accountResult),
25
- descriptor('resources', [profile()], resourcesResult),
26
- descriptor('begin', [profile()], beginResult),
27
- descriptor('loginStatus', [login()], loginResult),
28
- descriptor('cancelLogin', [login()], loginResult),
24
+ descriptor('status', [profile()], accountResult),
25
+ descriptor('resources', [profile()], resourcesResult),
26
+ descriptor('begin', [profile()], beginResult),
27
+ descriptor('loginStatus', [login()], loginResult),
28
+ descriptor('cancelLogin', [login()], loginResult),
29
29
  descriptor('reconcile', [profile(), options()], accountResult),
30
30
  descriptor('selectEnterpriseModel', [profile(), jsonParameter('options', enterpriseSelectionOptionsSchema, `${pkg}#EnterpriseSelectionOptions`)], enterpriseSelectionResult),
31
- descriptor('logout', [profile()], accountResult),
32
- descriptor('management', [], managementResult),
33
- descriptor('activate', [profile()], managementResult),
34
- descriptor('configure', [profile()], managementResult),
35
- descriptor('addCustom', [baseURL()], managementResult),
36
- descriptor('updateCustom', [profile(), baseURL()], managementResult),
37
- descriptor('removeProfile', [profile()], managementResult),
38
- descriptor('configureModels', [profile(), modelMode(), models()], managementResult),
39
- descriptor('restart', [], restartResult),
40
- ],
41
- }
42
-
43
- export default TYPERT_REMOTE
31
+ descriptor('logout', [profile()], accountResult),
32
+ descriptor('management', [], managementResult),
33
+ descriptor('activate', [profile()], managementResult),
34
+ descriptor('configure', [profile()], managementResult),
35
+ descriptor('addCustom', [baseURL()], managementResult),
36
+ descriptor('updateCustom', [profile(), baseURL()], managementResult),
37
+ descriptor('removeProfile', [profile()], managementResult),
38
+ descriptor('configureModels', [profile(), modelMode(), models()], managementResult),
39
+ descriptor('restart', [], restartResult),
40
+ ],
41
+ }
42
+
43
+ export default TYPERT_REMOTE
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eduwork/dsh-oidc",
3
- "version": "0.2.3",
4
- "description": "Standards-based OIDC identity, enterprise API-key binding, declarative branding, and OpenAI-compatible model integration for DeepSeek Harness",
3
+ "version": "0.3.0-dev.1",
4
+ "description": "Standards-based OIDC identity, token-authorized model access, declarative branding, and OpenAI-compatible model integration for DeepSeek Harness",
5
5
  "keywords": [
6
6
  "deepseek-harness",
7
7
  "dsh",
@@ -33,7 +33,7 @@
33
33
  "protocol/openapi.yaml",
34
34
  "protocol/resources.openapi.yaml",
35
35
  "README.md",
36
- "README.en.md",
36
+ "README_EN.md",
37
37
  "CODE_OF_CONDUCT.md",
38
38
  "CODE_OF_CONDUCT.en.md",
39
39
  "CONTRIBUTING.md",
@@ -97,12 +97,13 @@
97
97
  },
98
98
  "repository": {
99
99
  "type": "git",
100
- "url": "git+https://github.com/freedomkk-qfeng/dsh-oidc.git"
100
+ "url": "git+https://github.com/ecnu/EduWork.git",
101
+ "directory": "packages/dsh-oidc"
101
102
  },
102
103
  "bugs": {
103
- "url": "https://github.com/freedomkk-qfeng/dsh-oidc/issues"
104
+ "url": "https://github.com/ecnu/EduWork/issues"
104
105
  },
105
- "homepage": "https://github.com/freedomkk-qfeng/dsh-oidc#readme",
106
+ "homepage": "https://github.com/ecnu/EduWork/tree/main/packages/dsh-oidc#readme",
106
107
  "license": "MIT",
107
108
  "dependencies": {
108
109
  "zod": "4.4.3"