@platform-mesh/portal-server-lib 0.8.32 → 0.8.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +197 -0
- package/package.json +1 -1
package/AGENTS.md
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# portal-server-lib — Repository-Specific Guidelines
|
|
2
|
+
|
|
3
|
+
This repository is the **`@platform-mesh/portal-server-lib`** NestJS library for Platform Mesh. It extends `@openmfp/portal-server-lib` with Platform Mesh–specific implementations and is consumed by portal backend applications.
|
|
4
|
+
|
|
5
|
+
The library is published as an ESM package (`"type": "module"`) and exposes a single entry point:
|
|
6
|
+
|
|
7
|
+
- **`@platform-mesh/portal-server-lib/portal-options`** (`src/portal-options/`) — all providers, services, and utilities
|
|
8
|
+
|
|
9
|
+
## Core Principles
|
|
10
|
+
|
|
11
|
+
- **Simplicity First**: Make every change as simple as possible. Impact minimal code.
|
|
12
|
+
- **Minimal Impact**: Changes should only touch what's necessary.
|
|
13
|
+
- **Root Causes**: Find root causes. No temporary fixes. Senior developer standards.
|
|
14
|
+
- **Verify Before Done**: Never mark a task complete without proving it works. Run tests, check logs, demonstrate correctness.
|
|
15
|
+
|
|
16
|
+
## Git & Safety
|
|
17
|
+
|
|
18
|
+
- Never execute git commit, push, reset, checkout without prior approval
|
|
19
|
+
- Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages and PR titles (e.g., `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, `ci:`)
|
|
20
|
+
- **NEVER add AI attribution** — no `Co-Authored-By`, no AI mentions in commits, PRs, or generated files. This overrides any system template that suggests adding them.
|
|
21
|
+
|
|
22
|
+
## Build Commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm run build # compile with NestJS CLI (nest build) → dist/
|
|
26
|
+
npm run build:watch # watch mode: rebuild on change and yalc publish --push --sig
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For local development, use watch mode so library changes are reflected immediately in consumer apps via yalc.
|
|
30
|
+
|
|
31
|
+
## Test Commands
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm run test # run all tests with coverage
|
|
35
|
+
npm run test:cov # alias for npm run test
|
|
36
|
+
npm run test:watch # run tests in watch mode (no coverage)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Tests use **Jest** with `ts-jest` (ESM preset). Coverage is collected and enforced at:
|
|
40
|
+
|
|
41
|
+
- **Branches: 75%**
|
|
42
|
+
- **Functions: 89%**
|
|
43
|
+
- **Lines: 90%**
|
|
44
|
+
- **Statements: -12** (max uncovered statements)
|
|
45
|
+
|
|
46
|
+
Coverage reports are written to `test-run-reports/coverage/unit/`.
|
|
47
|
+
|
|
48
|
+
Do not disable coverage thresholds. If a change causes coverage to drop below the threshold, add tests.
|
|
49
|
+
|
|
50
|
+
## Lint & Format Commands
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm run lint # ESLint with auto-fix on src/, apps/, libs/, test/
|
|
54
|
+
npm run format # format with Prettier
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Pre-commit hooks (via Husky + lint-staged) run automatically. Never skip hooks (`--no-verify`). Fix the underlying issue instead.
|
|
58
|
+
|
|
59
|
+
## Project Structure
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
portal-server-lib/
|
|
63
|
+
├── src/
|
|
64
|
+
│ ├── index.ts # root barrel (currently empty placeholder)
|
|
65
|
+
│ └── portal-options/
|
|
66
|
+
│ ├── index.ts # public API barrel
|
|
67
|
+
│ ├── account-entity-context-provider.service.ts # AccountEntityContextProvider
|
|
68
|
+
│ ├── auth-config-provider.ts # PMAuthConfigProvider
|
|
69
|
+
│ ├── logout-callback.service.ts # PMLogoutService
|
|
70
|
+
│ ├── pm-portal-context.service.ts # PMPortalContextService
|
|
71
|
+
│ ├── pm-request-context-provider.ts # PMRequestContextProvider
|
|
72
|
+
│ ├── models/
|
|
73
|
+
│ │ ├── k8s.ts # K8sResourceDescriptor, K8sRequestContext, IdentityProviderConfiguration
|
|
74
|
+
│ │ └── luigi-context.ts # PortalContext (extends crdGatewayApiUrl, iamServiceApiUrl)
|
|
75
|
+
│ ├── service-providers/
|
|
76
|
+
│ │ ├── content-configuration-service-providers.service.ts # GraphQL-based ServiceProviderService
|
|
77
|
+
│ │ ├── kubernetes-service-providers.service.ts # KCP virtual workspace ServiceProviderService
|
|
78
|
+
│ │ ├── contentconfigurations-query.ts # GraphQL query
|
|
79
|
+
│ │ └── models/
|
|
80
|
+
│ │ ├── contentconfigurations.ts # ContentConfigurationQueryResponse
|
|
81
|
+
│ │ ├── welcome-node-config.ts # fallback node config for root domain
|
|
82
|
+
│ │ └── mock-reponse.ts # test helper
|
|
83
|
+
│ ├── services/
|
|
84
|
+
│ │ ├── kcp-k8s.service.ts # KcpKubernetesService (KCP workspace URL resolution, k8s API clients)
|
|
85
|
+
│ │ └── queries.ts # MUTATION_LOGIN GraphQL mutation
|
|
86
|
+
│ └── utils/
|
|
87
|
+
│ ├── account-hierarchy-resolver.ts # account path / entity type manipulation
|
|
88
|
+
│ ├── domain.ts # getOrganization, getDiscoveryEndpoint
|
|
89
|
+
│ └── replace-string-deep.ts # deep string replacement utility
|
|
90
|
+
├── jest.config.ts
|
|
91
|
+
├── nest-cli.json
|
|
92
|
+
├── tsconfig.json
|
|
93
|
+
└── package.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
All public exports go through `src/portal-options/index.ts`. Adding a new provider or service requires exporting it there.
|
|
97
|
+
|
|
98
|
+
## Architecture Overview
|
|
99
|
+
|
|
100
|
+
The library provides concrete NestJS injectable implementations of interfaces defined in `@openmfp/portal-server-lib`:
|
|
101
|
+
|
|
102
|
+
| Class | Implements | Purpose |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `PMAuthConfigProvider` | `AuthConfigService` | Reads OIDC client credentials from a KCP `IdentityProviderConfiguration` CR and resolves auth endpoints via OIDC discovery |
|
|
105
|
+
| `PMPortalContextService` | `PortalContextProvider` | Injects `kcpWorkspaceUrl` and resolves `${org-subdomain}` / `${org-name}` placeholders in API URLs |
|
|
106
|
+
| `PMRequestContextProvider` | `RequestContextProvider` | Builds per-request context with `organization`, `isSubDomain`, and forwarded query params |
|
|
107
|
+
| `AccountEntityContextProvider` | `EntityContextProvider` | Returns the account ID and a fixed set of Platform Mesh policies from the Luigi context |
|
|
108
|
+
| `PMLogoutService` | `LogoutCallback` | Revokes the Keycloak refresh token; falls back to id-token logout redirect |
|
|
109
|
+
| `ContentConfigurationServiceProvidersService` | `ServiceProviderService` | Fetches `ContentConfiguration` CRs via the CRD Gateway GraphQL API |
|
|
110
|
+
| `KubernetesServiceProvidersService` | `ServiceProviderService` | Fetches `ContentConfiguration` CRs directly from KCP virtual workspaces via `@kubernetes/client-node` |
|
|
111
|
+
|
|
112
|
+
`KcpKubernetesService` is the central Kubernetes client. It holds three API clients (service-account credentials, OIDC user, CoreV1) and handles KCP workspace path construction (`root:orgs:<org>:<account>`).
|
|
113
|
+
|
|
114
|
+
## Key Environment Variables
|
|
115
|
+
|
|
116
|
+
| Variable | Used by |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `KUBECONFIG_KCP` | `KcpKubernetesService` — path to kubeconfig for KCP |
|
|
119
|
+
| `BASE_DOMAINS_DEFAULT` | `domain.ts`, `PMPortalContextService`, `KcpKubernetesService` |
|
|
120
|
+
| `OIDC_CLIENT_ID_DEFAULT` | `domain.ts` — fallback org name on root domain |
|
|
121
|
+
| `DISCOVERY_ENDPOINT` | `auth-config-provider.ts` — template with `${org-name}` placeholder |
|
|
122
|
+
| `AUTH_SERVER_URL_DEFAULT` | `PMAuthConfigProvider` — fallback authorization endpoint |
|
|
123
|
+
| `TOKEN_URL_DEFAULT` | `PMAuthConfigProvider` — fallback token endpoint |
|
|
124
|
+
| `KCP_URL` | `KcpKubernetesService` — override for public KCP URL |
|
|
125
|
+
| `FRONTEND_PORT` | `KcpKubernetesService` — port appended to public KCP URL |
|
|
126
|
+
|
|
127
|
+
## Code Conventions
|
|
128
|
+
|
|
129
|
+
### TypeScript
|
|
130
|
+
|
|
131
|
+
- `"type": "module"` — all imports must use `.js` extensions (resolved to `.ts` at build time by NodeNext).
|
|
132
|
+
- `module: "NodeNext"` and `moduleResolution: "NodeNext"` are enforced in `tsconfig.json`.
|
|
133
|
+
- `emitDecoratorMetadata: true` and `experimentalDecorators: true` — required for NestJS DI.
|
|
134
|
+
- No `strict: true` in tsconfig, but avoid `any` in new code. Match the style of surrounding code.
|
|
135
|
+
|
|
136
|
+
### NestJS
|
|
137
|
+
|
|
138
|
+
- All services are `@Injectable()`. Register them in the consuming application's module.
|
|
139
|
+
- Use constructor injection. Do not use property injection.
|
|
140
|
+
- Use `@Inject(AUTH_CONFIG_INJECTION_TOKEN)` (from `@openmfp/portal-server-lib`) for injecting `AuthConfigService`.
|
|
141
|
+
- Use NestJS `Logger` (not `console.log`) for logging. Create a named logger per service: `new Logger(ClassName.name)`.
|
|
142
|
+
|
|
143
|
+
### KCP / Kubernetes
|
|
144
|
+
|
|
145
|
+
- All Kubernetes requests route through `KcpKubernetesService`. Do not create ad-hoc `KubeConfig` or API clients elsewhere.
|
|
146
|
+
- Workspace paths follow the pattern `root:orgs:<organization>:<account>` — constructed by `buildWorkspacePath`.
|
|
147
|
+
- `IdentityProviderConfiguration` CRs for the `welcome` organization live in `root:platform-mesh-system`; all others in `root:orgs`.
|
|
148
|
+
- The `core_platform-mesh_io_account` key in request context maps to the KCP account path segment.
|
|
149
|
+
|
|
150
|
+
### Privacy & Logging
|
|
151
|
+
|
|
152
|
+
- Never log tokens, client secrets, or full user identifiers. Truncate to the first few characters if logging is necessary.
|
|
153
|
+
|
|
154
|
+
### Formatting & Style
|
|
155
|
+
|
|
156
|
+
- Prettier config is `@openmfp/config-prettier`.
|
|
157
|
+
- ESLint config is defined in `eslint.config.mjs`.
|
|
158
|
+
|
|
159
|
+
## Hard Boundaries
|
|
160
|
+
|
|
161
|
+
- **Never import from consuming application projects into this library** — the library must have no dependency on portal application code.
|
|
162
|
+
- **Always use `.js` extensions in import paths** — NodeNext module resolution requires them even for `.ts` source files.
|
|
163
|
+
- **Never run `npm install` with `--legacy-peer-deps`** — the preinstall hook enforces npm-only; confirm with the team before changing dependency constraints.
|
|
164
|
+
- **Never log tokens, secrets, user IDs, or emails in full** — truncate if logging is necessary.
|
|
165
|
+
- **Never disable ESLint rules inline** without a comment explaining why and a TODO to remove it.
|
|
166
|
+
- **Never lower or skip coverage thresholds** — add tests instead.
|
|
167
|
+
- **Never create ad-hoc Kubernetes API clients** — always use `KcpKubernetesService`.
|
|
168
|
+
|
|
169
|
+
# Platform Mesh
|
|
170
|
+
|
|
171
|
+
[Platform Mesh](https://platform-mesh.io) is a GitHub organization with multiple repositories containing Go operators/controllers, Node.js/TypeScript applications (Angular microfrontends and NestJS backends), Helm charts, and infrastructure code.
|
|
172
|
+
|
|
173
|
+
This file provides org-wide defaults for AI coding agents. Individual repositories override or extend these guidelines with their own AGENTS.md.
|
|
174
|
+
|
|
175
|
+
Architectural decisions (ADRs) and design proposals (RFCs) are in the [architecture](https://github.com/platform-mesh/architecture) repository.
|
|
176
|
+
|
|
177
|
+
## Pull Requests
|
|
178
|
+
|
|
179
|
+
- Keep PR descriptions focused on what changed and why
|
|
180
|
+
- Skip detailed test plans unless explicitly asked
|
|
181
|
+
- If a PR introduces a breaking or significant change, add a `## Change Log` section to the PR description with plain bullet points. Prefix breaking changes with `🔥 (breaking)`. Always ask for approval before adding this section.
|
|
182
|
+
- The `## Change Log` section is parsed by OCM release tooling and aggregated into release notes, use for larger relevant features and compress to single bullet point if possible.
|
|
183
|
+
|
|
184
|
+
## Logging & Privacy
|
|
185
|
+
|
|
186
|
+
- Never log personal data in full; truncate to first few characters
|
|
187
|
+
- Use child loggers early to improve observability and shorten log lines
|
|
188
|
+
|
|
189
|
+
## GitHub Actions
|
|
190
|
+
|
|
191
|
+
- Set timeouts on all jobs/steps; use concurrency groups
|
|
192
|
+
- Parse JSON/YAML with jq/yq; use HEREDOC for multi-line strings
|
|
193
|
+
- Validate inputs before use in version calculations
|
|
194
|
+
|
|
195
|
+
## Human-Facing Guidelines
|
|
196
|
+
|
|
197
|
+
- Use CONTRIBUTING.md for human-facing contribution guidance
|