| metadata_json |
{"scope":"@juhai","name":& {"scope":"@juhai","name":"client-credential","description":"Reference-only remote ServiceCredentialPort for the explicit M2 lease HTTP candidate; uncached M1 bearer per call and bounded fail-closed transport","license":"UNLICENSED","development_dependencies":{"@juhai/kernel":"0.24.0","@types/node":"22.19.20","typescript":"5.9.3","vitest":"2.1.9"},"peer_dependencies":{"@juhai/kernel":"0.24.0"},"readme":"# @juhai/client-credential\n\n`1.0.0-rc.7` implements kernel `ServiceCredentialPort` against the explicit M2 HTTP candidate. Registry metadata and the packaged provenance.json identify the published version; publication does not imply deployment in real HR/OS applications. Peer `@juhai/kernel` is pinned to `0.24.0`; no module dependency or host schema generation is required.\n\n```ts\nimport { createRemoteServiceCredentialPort, type RemoteCredentialPort } from \"@juhai/client-credential\";\nconst credential = createRemoteServiceCredentialPort({\n baseUrl: \"https://platform.example/api\",\n token: async (request, signal) =\u003e machineTokenFor(request, signal),\n}) as RemoteCredentialPort;\nconst lease = await credential.lease(request);\ncredential.close();\n```\n\nThe fixed route is `POST /v1/credential-leases`. The provider must return a current M1 service/job token bound to the canonical tenant, actor, application and resource audience. Every call takes a fresh bearer; neither tokens nor references are cached. Callers control retries with the original request ID. The SDK returns only `credentialRef`, `expiresAt`, and `port`; material resolution, workload injection and renewal are separate boundaries.\n\nUnconfigured calls retain the kernel fail-closed port. Configured calls throw sanitized `CredentialClientError` values with `code`, `port: \"serviceCredential\"` and an optional HTTP `status`. Provider, transport and response reading share a timeout (default 5000 ms, maximum 30000 ms), including dependencies ignoring cancellation. `close()` aborts in-flight calls. HTTPS is required; loopback HTTP needs `allowLoopbackHttp: true`. Redirects, URL credentials, queries and fragments are forbidden. Responses with extra material fields, malformed references, expired leases or bodies larger than 16 KiB are rejected. Local expiry cannot exceed the requested TTL measured from the start of the call.\n\nM2 enables this candidate only with `PLATFORM_CREDENTIAL_HTTP_ENABLED=1`, `NODE_ENV=test|development`, `AUTH_MODE=jwt`, an ordinary `DATABASE_URL_CREDENTIAL` role and forced RLS. `CREDENTIAL_IDENTITY_TRUST_JSON` is a fixed array of canonical tenant/resource bindings:\n\n```json\n[{\"tenantId\":\"ten_01kkkkkkkkkkkkkkkkkkkkkkkk\",\"issuer\":\"https://identity.example/t/example\",\"audience\":\"RESOURCE_APPLICATION_ID\",\"clientId\":\"srv_RESOURCE_RECEIVER_ID\",\"clientSecretEnv\":\"CREDENTIAL_M1_RECEIVER_SECRET\"}]\n```\n\nThe receiver credential belongs to the audience's resource application and authenticates M1 introspection independently of the caller bearer. M2 also needs `CREDENTIAL_OPENBAO_ADDRESS`, `CREDENTIAL_OPENBAO_TOKEN_ENV`, `CREDENTIAL_OPENBAO_MOUNT`, and `CREDENTIAL_OPENBAO_PREFIX`, with a least-privileged current token in the named environment variable. Secret values never become request-body fields. Turbo forwards `CREDENTIAL_*`; use this prefix for the named receiver and OpenBao secret environment variables when launching through Turbo. Trusted operator policy installation and controlled material resolution remain separate. Production workload injection, renewal, Catalog E2 activation and target-environment signoff are pending.\n\nVerification includes 16 SDK behavior cases, the shared port fixture's three profiles, and `runtime/test/e2e/credential-m1-http.test.ts` using real M1, an ordinary-role M2 database and disposable initialized/unsealed OpenBao. `pnpm mainline:check` requires that suite and its 20-sample revocation report.\n","repository":{"type":"git","url":"git@gitea.g-hi.com:luoanwu/enterprise-platform.git"}}... |