forte-drop, forte-drop-mcp and forte-drop-postgresql lived under apps/base/
but were only ever wired into the upc-dev overlay (never listed in
apps/base/kustomization.yaml). They carry hackathon-domain hardcoded values
and must not sync to upc-prod, so they belong in the overlay alongside
dbunk-demo — per danijel.simeunovic's review on PR #18.
- git mv the three dirs into apps/overlays/upc-dev/ (history preserved)
- rewrite overlay kustomization refs from ../../base/forte-drop* to local
- repoint forte-drop-postgresql Application path
apps/base/... -> apps/overlays/upc-dev/forte-drop-postgresql/resources
Render-verified: kubectl kustomize apps/overlays/upc-dev differs only by the
postgres path line; apps/overlays/upc-prod render byte-identical (forte-drop
never reaches prod).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per platform review (danijel):
- keycloak-client-forte-drop: add the secret{} block telling the
registrar where to write the credential Secret + key names
(forte-drop-oidc-credentials, client-id/client-secret). The
forte-helm oidc sidecar consumes that registrar-created Secret —
no manual auth-oidc SealedSecret step (removed that NOTE).
- Delete keycloak-client-forte-drop-mcp: auth.type: mcp auto-registers
the MCP client; no manual config needed.
- Re-seal forte-drop-secrets with all shared env (BASE_DOMAIN, PG*,
S3_*, PASSWORD_GATE_SECRET) so both deployments get identical values
via envSecretName (values extraEnv now carries only APP_MODE).
ai-review: a commented-out resource line reads as GitOps debt. Replace
the '# - auth-oidc-sealed.yaml' line with an explicit NOTE explaining
it's a deliberate post-deploy step (needs the registrar-generated
client-secret), not a disabled resource.
Per reviewer (danijel): forte-drop's DB deployment belongs in apps/,
not infra/. Straight relocation — same structure (Application +
resources/ subdir), source.path updated to apps/base/forte-drop-postgresql/resources,
wired into apps/overlays/upc-dev. Backup CronJob + RESTORE.md + sealed
pg creds move with it.
Consolidates the whole forte-drop deployment (postgres + web + mcp)
under apps/. The infra PR (#17) is now superseded by this.
Codex review: the apps overlay applies namespaced resources
(keycloak-client Secrets, forte-drop-secrets, PDB) to forte-drop, but
no base created the namespace — first sync on a fresh cluster raced
ahead of the Applications' CreateNamespace and failed with
'namespaces forte-drop not found' until a retry.
Add an explicit Namespace at sync-wave -1 so it exists before the
wave-0 namespaced resources (covers both web + mcp bases via the
shared parent). Prune=false keeps removing a base from cascade-
deleting the namespace + postgres data + the other deployment.
Sealed forte-drop-secrets with the real UpCloud Managed Object Storage
creds (existing drops bucket), PG creds matching the deployed
forte-drop-pg-creds, and PASSWORD_GATE_SECRET. Consumed by both web +
mcp deployments (envSecretName) and the pg-backup CronJob (S3 creds).
Two ArgoCD apps from the same forte-drop image:
- forte-drop (web): admin + public drops, sidecar in oidc mode,
ingress drop-k8s.hackathon.forteapps.net.
- forte-drop-mcp (mcp): MCP-over-HTTP, sidecar in mcp mode,
ingress mcp.drop-k8s.hackathon.forteapps.net.
Plus two labeled Keycloak client config Secrets — the registrar
creates the OIDC clients in the forte realm within ~2 min.
Sealed secrets (forte-drop-secrets + auth-oidc) added in a
follow-up commit by the maintainer:
cd /Users/sten/dev/work/forte_k8/launchpad
kubeseal --format=yaml \
--controller-name=sealed-secrets-controller \
--controller-namespace=kube-system \
< private/forte-drop-secrets.yaml \
> apps/base/forte-drop/forte-drop-secrets-sealed.yaml
# auth-oidc: wait for registrar, copy client-secret into private/,
# then seal as apps/base/forte-drop/auth-oidc-sealed.yaml.
# (mcp deployment is sidecar type=mcp — no auth-oidc Secret needed;
# only the web deployment requires it.)
forte-drop, forte-drop-mcp and forte-drop-postgresql lived under apps/base/
but were only ever wired into the upc-dev overlay (never listed in
apps/base/kustomization.yaml). They carry hackathon-domain hardcoded values
and must not sync to upc-prod, so they belong in the overlay alongside
dbunk-demo — per danijel.simeunovic's review on PR #18.
- git mv the three dirs into apps/overlays/upc-dev/ (history preserved)
- rewrite overlay kustomization refs from ../../base/forte-drop* to local
- repoint forte-drop-postgresql Application path
apps/base/... -> apps/overlays/upc-dev/forte-drop-postgresql/resources
Render-verified: kubectl kustomize apps/overlays/upc-dev differs only by the
postgres path line; apps/overlays/upc-prod render byte-identical (forte-drop
never reaches prod).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per platform review (danijel):
- keycloak-client-forte-drop: add the secret{} block telling the
registrar where to write the credential Secret + key names
(forte-drop-oidc-credentials, client-id/client-secret). The
forte-helm oidc sidecar consumes that registrar-created Secret —
no manual auth-oidc SealedSecret step (removed that NOTE).
- Delete keycloak-client-forte-drop-mcp: auth.type: mcp auto-registers
the MCP client; no manual config needed.
- Re-seal forte-drop-secrets with all shared env (BASE_DOMAIN, PG*,
S3_*, PASSWORD_GATE_SECRET) so both deployments get identical values
via envSecretName (values extraEnv now carries only APP_MODE).
ai-review: a commented-out resource line reads as GitOps debt. Replace
the '# - auth-oidc-sealed.yaml' line with an explicit NOTE explaining
it's a deliberate post-deploy step (needs the registrar-generated
client-secret), not a disabled resource.
Per reviewer (danijel): forte-drop's DB deployment belongs in apps/,
not infra/. Straight relocation — same structure (Application +
resources/ subdir), source.path updated to apps/base/forte-drop-postgresql/resources,
wired into apps/overlays/upc-dev. Backup CronJob + RESTORE.md + sealed
pg creds move with it.
Consolidates the whole forte-drop deployment (postgres + web + mcp)
under apps/. The infra PR (#17) is now superseded by this.
Codex review: the apps overlay applies namespaced resources
(keycloak-client Secrets, forte-drop-secrets, PDB) to forte-drop, but
no base created the namespace — first sync on a fresh cluster raced
ahead of the Applications' CreateNamespace and failed with
'namespaces forte-drop not found' until a retry.
Add an explicit Namespace at sync-wave -1 so it exists before the
wave-0 namespaced resources (covers both web + mcp bases via the
shared parent). Prune=false keeps removing a base from cascade-
deleting the namespace + postgres data + the other deployment.
Sealed forte-drop-secrets with the real UpCloud Managed Object Storage
creds (existing drops bucket), PG creds matching the deployed
forte-drop-pg-creds, and PASSWORD_GATE_SECRET. Consumed by both web +
mcp deployments (envSecretName) and the pg-backup CronJob (S3 creds).
forte-drop and forte-drop-mcp have hackathon-domain values hardcoded
(drop-k8s.hackathon.forteapps.net). Listing them in apps/base/
syncs them to both upc-dev and upc-prod overlays — prod sync would
create broken Applications pointing at non-existent prod ingress.
Move references to apps/overlays/upc-dev/ only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two ArgoCD apps from the same forte-drop image:
- forte-drop (web): admin + public drops, sidecar in oidc mode,
ingress drop-k8s.hackathon.forteapps.net.
- forte-drop-mcp (mcp): MCP-over-HTTP, sidecar in mcp mode,
ingress mcp.drop-k8s.hackathon.forteapps.net.
Plus two labeled Keycloak client config Secrets — the registrar
creates the OIDC clients in the forte realm within ~2 min.
Sealed secrets (forte-drop-secrets + auth-oidc) added in a
follow-up commit by the maintainer:
cd /Users/sten/dev/work/forte_k8/launchpad
kubeseal --format=yaml \
--controller-name=sealed-secrets-controller \
--controller-namespace=kube-system \
< private/forte-drop-secrets.yaml \
> apps/base/forte-drop/forte-drop-secrets-sealed.yaml
# auth-oidc: wait for registrar, copy client-secret into private/,
# then seal as apps/base/forte-drop/auth-oidc-sealed.yaml.
# (mcp deployment is sidecar type=mcp — no auth-oidc Secret needed;
# only the web deployment requires it.)
2026-05-28 16:47:38 +02:00
17 changed files with 44 additions and 150 deletions
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
## Before exploring, read these
- **`CONTEXT.md`** at the repo root, or
- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
## File structure
Single-context repo (most repos):
```
/
├── CONTEXT.md
├── docs/adr/
│ ├── 0001-event-sourced-orders.md
│ └── 0002-postgres-for-write-model.md
└── src/
```
## Use the glossary's vocabulary
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).
## Flag ADR conflicts
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_
or via API: `curl -X POST "https://git.forteapps.net/api/v1/repos/Forte/launchpad/issues" -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" -d '{"title":"...","body":"..."}'`
- **Read an issue**: `tea issue view <number>` or API `GET /api/v1/repos/Forte/launchpad/issues/<number>`
- **List issues**: `tea issue list` or API `GET /api/v1/repos/Forte/launchpad/issues?state=open`
- **Comment on an issue**: `tea issue comment <number> "..."` or API `POST /api/v1/repos/Forte/launchpad/issues/<number>/comments`
- **Apply labels**: API `POST /api/v1/repos/Forte/launchpad/issues/<number>/labels` with `{"labels": [<label_id>]}`
- **Close**: API `PATCH /api/v1/repos/Forte/launchpad/issues/<number>` with `{"state": "closed"}`
Infer the repo from `git remote -v`.
## Pull requests as a triage surface
**PRs as a request surface: no.**
## When a skill says "publish to the issue tracker"
Create a Gitea issue.
## When a skill says "fetch the relevant ticket"
Fetch the issue via API or `tea issue view <number>`.
## Wayfinding operations
Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.
- **Map**: a single issue labelled `wayfinder:map`, holding the Destination / Notes / Decisions-so-far / Fog body.
- Create: `POST /api/v1/repos/Forte/launchpad/issues` with `{"title":"...","body":"...","labels":[<wayfinder:map label id>]}`
- **Child ticket**: an issue carrying `Part of #<map>` at the top of its body and a `wayfinder:<type>` label (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
- **Blocking**: Gitea does not have native issue dependencies. Fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every issue it lists is closed.
- **Frontier query**: list the map's open children — `GET /api/v1/repos/Forte/launchpad/issues?state=open&labels=wayfinder:research,wayfinder:prototype,wayfinder:grilling,wayfinder:task` — then filter to those whose body starts with `Part of #<map>`. Drop any with an open issue in their `Blocked by` line, or with an assignee. First in map order wins.
- **Claim**: `PATCH /api/v1/repos/Forte/launchpad/issues/<n>` with `{"assignees":["<username>"]}` — the session's first write.
- **Resolve**: post the answer as a comment (`POST .../comments`), close the issue (`PATCH` with `{"state":"closed"}`), then append a context pointer (gist + link) to the map's Decisions-so-far by editing the map issue body.
description:Teknisk kompetanse fra offentlige anbud
icon:forte
- Forte Drop:
href:https://drop.hackathon.forteapps.net
description:Self-hosted HTML-drops + MCP for Claude
icon:forte
- Forte Feedback:
href:https://feedback.forteapps.net
description:Fortes internal feedback app
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.