From 6e3dd2244275b2a9bc71dde7d25036e02ca01e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= <169163068+ThomasMuellerKiteworks@users.noreply.github.com> Date: Mon, 31 Aug 2026 16:33:02 +0200 Subject: [PATCH] chore: adopt the AGENTS.md convention (fold CLAUDE.md into AGENTS.md) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Thomas Müller <169163068+ThomasMuellerKiteworks@users.noreply.github.com> --- AGENTS.md | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 121 +----------------------------- agents.md | 88 ---------------------- 3 files changed, 221 insertions(+), 208 deletions(-) create mode 100644 AGENTS.md mode change 100644 => 120000 CLAUDE.md delete mode 100644 agents.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..f97d71bf4 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,220 @@ +# AGENTS.md — web-extensions + +## Repository Overview + +A collection of supplementary ownCloud Web extensions maintained outside the main web repository. Each extension in `packages/web-app-*` is a standalone Vue 3 + TypeScript app that integrates into the oCIS (ownCloud Infinite Scale) platform. + +- **Classification:** oCIS +- **Activity Status:** Active +- **License:** AGPL-3.0 +- **Language:** Vue.js, TypeScript + +## Architecture & Key Paths + +- `packages/` — pnpm workspace packages. `packages/web-app-*` are the extensions + themselves (file viewers/editors such as `web-app-draw-io` and + `web-app-json-viewer`; workflow additions such as `web-app-advanced-search`, + `web-app-cast`, `web-app-importer`, `web-app-unzip`; and a family of + `web-app-ai-*` sidebars and actions). `packages/ai-llm-proxy` is not a Vue app — + see **AI extensions** below. Enumerate `packages/` rather than trusting a list + in a doc; extensions are added often. +- `docs/` — Documentation (starting guide, release workflow) +- `docker/` — Docker build files +- `dev/` — Development environment configuration, including + `dev/docker/csp.yaml` and `dev/docker/ocis.apps.yaml` +- `support/` — Support scripts +- `Makefile` — Build orchestration +- `package.json` — Root package with scripts +- `pnpm-workspace.yaml` — pnpm monorepo workspace configuration +- `playwright.config.ts` — Root Playwright config; each package extends it +- `gettext.config.cjs` — Configures translation-string extraction +- `eslint.config.js` — ESLint configuration + +## Development Conventions + +- pnpm monorepo with workspace packages +- Prettier for code formatting +- Vite for building individual extensions +- Playwright for e2e testing +- GitHub Actions CI +- Each extension is independently versioned and releasable +- Release workflow documented in `docs/RELEASE_WORKFLOW.md` + +## Build & Test Commands + +```bash +pnpm install # Install all dependencies +pnpm build # Build all extensions +pnpm build:w # Build all extensions in watch mode (development) +pnpm lint # Run ESLint across all packages +pnpm check:types # Run TypeScript checks across all packages +pnpm test:unit # Run all unit tests +pnpm test:e2e # Run all Playwright E2E tests +``` + +**Per-package** (replace `` with the package name, e.g. `draw-io`, +`advanced-search`): + +```bash +pnpm --filter build +pnpm --filter test:unit +pnpm --filter test:e2e +pnpm --filter check:types +``` + +**Local development environment:** + +```bash +pnpm build && docker compose up -d # Start full oCIS stack with all extensions mounted +docker compose down --remove-orphans # Stop +docker compose pull # Update non-extension images +``` + +Access the dev environment at `https://host.docker.internal:9200` +(login `admin`/`admin`). Requires `127.0.1.1 host.docker.internal` in `/etc/hosts`. + +**Translations:** + +```bash +make l10n-read # Extract gettext strings and create .pot template +make l10n-write # Generate translations.json from .po files +make l10n-push # Push source strings to Transifex +make l10n-pull # Pull translations from Transifex +``` + +## Extension Anatomy + +Every `web-app-*` package follows the same pattern: + +- **`src/index.ts`** — entry point; calls `defineWebApplication()` from + `@ownclouders/web-pkg` and returns `{ appInfo, routes, translations, extensions }` +- **`vite.config.ts`** — uses `defineConfig` from `@ownclouders/extension-sdk` + (a Vite wrapper) +- **`l10n/translations.json`** — compiled translation strings consumed by the app +- **`tests/unit/`** — Vitest unit tests using `@ownclouders/web-test-helpers` +- **`tests/e2e/`** — Playwright tests; each package has a `playwright.config.ts` + that extends the root one + +### Extension registration + +Extensions register capabilities via the `extensions` array returned from +`defineWebApplication`. The key extension types are: + +| Type | Purpose | Example | +|------|---------|---------| +| `AppWrapperRoute` | File editor (opens a file in the app) | draw-io, json-viewer | +| `sidebarPanel` | Adds a panel to the file detail sidebar | ai-doc-summary, chat-with-file | +| `action` | Context menu / file action | ai-doc-summary's "Summarize" action | +| `appMenuItem` | Entry in the global app switcher | draw-io | + +### Key dependencies + +- **`@ownclouders/web-pkg`** — core Web SDK: `defineWebApplication`, stores (Pinia), + composables, routing helpers, design system components (`oc-*`) +- **`@ownclouders/web-client`** — typed WebDAV/API client, `Resource` types +- **`@ownclouders/extension-sdk`** — Vite `defineConfig` wrapper for extension builds +- **`@ownclouders/web-test-helpers`** — `mount()` + `defaultPlugins()` for Vitest +- **`vue3-gettext`** — i18n; use `$gettext`/`$pgettext`/`$ngettext` in templates and + `useGettext()` in setup + +### Design system + +All UI must use the ownCloud Design System components from `@ownclouders/web-pkg`. +Do not use custom SVG icons when an `oc-icon` equivalent exists. Available icons: +`packages/design-system/src/assets/icons` in the `owncloud/web` repo. + +### Translations + +All user-facing strings must be wrapped with `$gettext()`, `$pgettext()` or +`$ngettext()` (for count-aware plurals). The `gettext.config.cjs` at the repo root +configures extraction, and translation files live in each package's `l10n/` +directory. Translations are managed via Transifex and synced automatically — do not +edit `.po` files or `translations.json` by hand. + +### AI extensions + +The `web-app-ai-*` packages use the sidebar and action extension patterns to add +AI-powered panels. They talk to an LLM through `packages/ai-llm-proxy`, which is a +plain Node.js HTTP server (not a Vue app) that validates oCIS OIDC tokens and +proxies requests to a configured LLM endpoint. The proxy is configured entirely via +environment variables (`LLM_ENDPOINT`, `LLM_API_KEY`, `OCIS_URL`, etc.). + +**Security requirement — origin validation:** any code path that calls the LLM proxy +(or any LLM endpoint) **must** validate the `Origin` header of incoming requests +against `OCIS_URL` and reject requests whose origin does not match. CORS headers +alone are browser-enforced and insufficient — the proxy must perform an explicit +server-side origin check and return `403` for unexpected origins. Never skip this +check when adding new LLM-calling code. + +### Docker Compose and CSP + +`docker-compose.yml` mounts each extension's `dist/` directory into the oCIS +container. When adding a new extension, add its `dist/` mount and update +`dev/docker/csp.yaml` if it needs additional CSP directives. + +### App configuration (`ocis.apps.yaml`) + +`dev/docker/ocis.apps.yaml` and `support/actions/ocis.apps.yaml` supply per-app +config (e.g. LLM endpoint, companion URL) to oCIS. The **key for each entry must +match the mount target directory**, not the package directory name or the app's +internal `applicationId`. + +These two files use different conventions because their mounts differ: + +- **`dev/docker/ocis.apps.yaml`** (used by `docker-compose.yml`) — mounts strip the + `web-app-` prefix (e.g. `./packages/web-app-chat-with-file/dist:/web/apps/chat-with-file`), + so the key is `chat-with-file`. +- **`support/actions/ocis.apps.yaml`** (used by CI at `.github/workflows/test.yml`) — + the workflow mounts using `${{matrix.app}}` verbatim as the target directory + (e.g. `/apps/web-app-chat-with-file`), so the key is `web-app-chat-with-file`. + +## Adding a New Extension + +1. Create `packages/web-app-/` following the structure of an existing extension +2. Add the `dist/` volume mount in `docker-compose.yml` +3. Provide an `l10n/` directory with the same structure as other extensions +4. Run `pnpm install` from the repo root after creating `package.json` + +## Releasing + +Releases use per-app signed tags on the merge commit: `{app-name}-v{version}` +(e.g. `draw-io-v0.4.1`). Each tag independently triggers CI to build, package and +publish that extension. Push tags one at a time — pushing all at once does not +reliably trigger the release workflow. See `docs/RELEASE_WORKFLOW.md` for the full +process. + +## Important Constraints + +- **AGPL-3.0 copyleft license:** The OSPO Apache 2.0 migration requires auditing this copyleft license. +- **Monorepo structure:** Each extension in `packages/` can be built and released independently. +- **oCIS dependency:** Extensions require oCIS and ownCloud Web to function. +- **Docker image:** Published as `owncloud/web-extensions` on Docker Hub. +- **External dependencies:** Some extensions (draw.io, external sites) embed or connect to third-party services. + + +## OSPO Policy Constraints + +### GitHub Actions +- **Only** use actions owned by `owncloud`, created by GitHub (`actions/*`), verified on the GitHub Marketplace, or verified by the ownCloud Maintainers. +- Pin all actions to their full commit SHA (not tags): `uses: actions/checkout@ # vX.Y.Z` +- Never introduce actions from unverified third parties. + +### Dependency Management +- Dependabot is configured for automated dependency updates. +- Review and merge Dependabot PRs as part of regular maintenance. +- Do not introduce new dependencies without discussion in an issue first. + +### Git Workflow +- **Rebase policy**: Always rebase; never create merge commits. Use `git pull --rebase` and `git rebase` before pushing. +- **Signed commits**: All commits **must** be PGP/GPG signed (`git commit -S -s`). +- **DCO sign-off**: Every commit needs a `Signed-off-by` line (`git commit -s`). +- **Conventional Commits & Squash Merge**: Use the [Conventional Commits](https://www.conventionalcommits.org/) format where the repository enforces it. Many repos use squash merge, where the PR title becomes the commit message on the default branch — apply Conventional Commits format to PR titles as well. A reusable GitHub Actions workflow enforces this. + +## Context for AI Agents + +- This is a pnpm monorepo containing multiple independent web extensions. +- Each extension in `packages/` has its own `package.json`, source code and build config. +- The `docs/starting_guide.md` explains how to add new extensions to the repository. +- Docker images bundle all extensions together for deployment. +- Extensions register with the oCIS Web runtime via the extension system API. +- Development environment uses Docker Compose with an oCIS backend. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index c9b0d2b51..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,120 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Commands - -```bash -pnpm install # Install all dependencies -pnpm build # Build all extensions -pnpm build:w # Build all extensions in watch mode (development) -pnpm lint # Run ESLint across all packages -pnpm check:types # Run TypeScript checks across all packages -pnpm test:unit # Run all unit tests -pnpm test:e2e # Run all Playwright E2E tests -``` - -**Per-package (replace `` with package name, e.g. `draw-io`, `advanced-search`):** -```bash -pnpm --filter build -pnpm --filter test:unit -pnpm --filter test:e2e -pnpm --filter check:types -``` - -**Local development environment:** -```bash -pnpm build && docker compose up -d # Start full oCIS stack with all extensions mounted -docker compose down --remove-orphans # Stop -docker compose pull # Update non-extension images -``` - -Access the dev environment at `https://host.docker.internal:9200` (login: `admin`/`admin`). Requires `127.0.1.1 host.docker.internal` in `/etc/hosts`. - -**Translations:** -```bash -make l10n-read # Extract gettext strings and create .pot template -make l10n-write # Generate translations.json from .po files -make l10n-push # Push source strings to Transifex -make l10n-pull # Pull translations from Transifex -``` - -## Architecture - -This is a **pnpm monorepo** (`pnpm-workspace.yaml`) of independent ownCloud Web extensions. Each extension in `packages/web-app-*` is a standalone Vue 3 + TypeScript app that integrates into the oCIS (ownCloud Infinite Scale) platform. - -### Extension anatomy - -Every `web-app-*` package follows the same pattern: - -- **`src/index.ts`** — entry point; calls `defineWebApplication()` from `@ownclouders/web-pkg` and returns `{ appInfo, routes, translations, extensions }` -- **`vite.config.ts`** — uses `defineConfig` from `@ownclouders/extension-sdk` (a Vite wrapper) -- **`l10n/translations.json`** — compiled translation strings consumed by the app -- **`tests/unit/`** — Vitest unit tests using `@ownclouders/web-test-helpers` -- **`tests/e2e/`** — Playwright tests; each package has a `playwright.config.ts` that extends the root `playwright.config.ts` - -### Extension registration - -Extensions register capabilities via the `extensions` array returned from `defineWebApplication`. The key extension types are: - -| Type | Purpose | Example | -|------|---------|---------| -| `AppWrapperRoute` | File editor (opens a file in the app) | draw-io, json-viewer | -| `sidebarPanel` | Adds a panel to the file detail sidebar | ai-doc-summary, chat-with-file | -| `action` | Context menu / file action | ai-doc-summary's "Summarize" action | -| `appMenuItem` | Entry in the global app switcher | draw-io | - -### Key dependencies - -- **`@ownclouders/web-pkg`** — core Web SDK: `defineWebApplication`, stores (Pinia), composables, routing helpers, design system components (`oc-*`) -- **`@ownclouders/web-client`** — typed WebDAV/API client, `Resource` types -- **`@ownclouders/extension-sdk`** — Vite `defineConfig` wrapper for extension builds -- **`@ownclouders/web-test-helpers`** — `mount()` + `defaultPlugins()` for Vitest -- **`vue3-gettext`** — i18n; use `$gettext`/`$pgettext`/`$ngettext` in templates and `useGettext()` in setup - -### AI extensions - -`packages/web-app-ai-doc-summary` and `packages/web-app-chat-with-file` use the sidebar extension pattern to add AI-powered panels. They communicate with an LLM through `packages/ai-llm-proxy`, which is a plain Node.js HTTP server (not a Vue app) that validates oCIS OIDC tokens and proxies requests to a configured LLM endpoint. The proxy is configured entirely via environment variables (`LLM_ENDPOINT`, `LLM_API_KEY`, `OCIS_URL`, etc.). - -**Security requirement — origin validation:** Any code path that calls the LLM proxy (or any LLM endpoint) **must** validate the `Origin` header of incoming requests against `OCIS_URL` and reject requests whose origin does not match. CORS headers alone are browser-enforced and insufficient — the proxy must perform an explicit server-side origin check and return `403` for unexpected origins. Never skip this check when adding new LLM-calling code. - -### Design system - -All UI must use the ownCloud Design System components from `@ownclouders/web-pkg`. Do not use custom SVG icons when an `oc-icon` equivalent exists. Available icons: `packages/design-system/src/assets/icons` in the `owncloud/web` repo. - -### Translations - -All user-facing strings must be wrapped with `$gettext()`, `$pgettext()`, or `$ngettext()` (for count-aware plurals). The `gettext.config.cjs` at the repo root configures extraction. Translation files live in each package's `l10n/` directory. Translations are managed via Transifex and synced automatically — do not edit `.po` files or `translations.json` by hand. - -### Docker Compose / CSP - -The `docker-compose.yml` mounts each extension's `dist/` directory into the oCIS container. When adding a new extension, add its `dist/` mount and update `dev/docker/csp.yaml` if it needs additional CSP directives. - -### App configuration (`ocis.apps.yaml`) - -`dev/docker/ocis.apps.yaml` and `support/actions/ocis.apps.yaml` supply per-app config (e.g. LLM endpoint, companion URL) to oCIS. The **key for each entry must match the mount target directory**, not the package directory name or the app's internal `applicationId`. - -These two files use different conventions because their mounts differ: -- **`dev/docker/ocis.apps.yaml`** (used by `docker-compose.yml`) — mounts strip the `web-app-` prefix (e.g. `./packages/web-app-chat-with-file/dist:/web/apps/chat-with-file`), so the key is `chat-with-file`. -- **`support/actions/ocis.apps.yaml`** (used by CI at `.github/workflows/test.yml`) — the workflow mounts using `${{matrix.app}}` verbatim as the target directory (e.g. `/apps/web-app-chat-with-file`), so the key is `web-app-chat-with-file`. - -## Adding a New Extension - -1. Create `packages/web-app-/` following the structure of an existing extension -2. Add the `dist/` volume mount in `docker-compose.yml` -3. Provide an `l10n/` directory with the same structure as other extensions -4. Run `pnpm install` from the repo root after creating `package.json` - -## Git Workflow - -All commits **must** be PGP/GPG signed and carry a DCO sign-off: - -```bash -git commit -S -s -m "feat(web-app-foo): add bar feature" -``` - -Use a rebase workflow — never create merge commits. PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/) format (enforced by CI). - -## Releasing - -Releases use per-app signed tags on the merge commit: `{app-name}-v{version}` (e.g. `draw-io-v0.4.1`). Each tag independently triggers CI to build, package, and publish that extension. Push tags one at a time — pushing all at once does not reliably trigger the release workflow. See `docs/RELEASE_WORKFLOW.md` for the full process. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 000000000..47dc3e3d8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/agents.md b/agents.md deleted file mode 100644 index 4b461de17..000000000 --- a/agents.md +++ /dev/null @@ -1,88 +0,0 @@ -# agents.md — web-extensions - -## Repository Overview - -A collection of supplementary ownCloud Web extensions maintained outside the main web repository. Includes extensions for draw.io, JSON viewing, file casting, advanced search, photo enhancements, file importing, progress bars, external sites and ZIP extraction. - -- **Classification:** oCIS -- **Activity Status:** Active -- **License:** AGPL-3.0 -- **Language:** Vue.js, TypeScript - -## Architecture & Key Paths - -- `packages/` — Monorepo containing individual extensions: - - `packages/web-app-advanced-search/` — Advanced search extension - - `packages/web-app-cast/` — File casting extension - - `packages/web-app-draw-io/` — Draw.io diagram integration - - `packages/web-app-external-sites/` — External site embedding - - `packages/web-app-importer/` — File import extension - - `packages/web-app-json-viewer/` — JSON file viewer - - `packages/web-app-photo-addon/` — Photo enhancement features - - `packages/web-app-progress-bars/` — Progress bar extension - - `packages/web-app-unzip/` — ZIP extraction extension -- `docs/` — Documentation (starting guide, release workflow) -- `docker/` — Docker build files -- `dev/` — Development environment configuration -- `support/` — Support scripts -- `Makefile` — Build orchestration -- `package.json` — Root package with scripts -- `pnpm-workspace.yaml` — pnpm monorepo workspace configuration -- `playwright.config.ts` — Playwright e2e test configuration -- `eslint.config.js` — ESLint configuration - -## Development Conventions - -- pnpm monorepo with workspace packages -- Prettier for code formatting -- Vite for building individual extensions -- Playwright for e2e testing -- GitHub Actions CI -- Each extension is independently versioned and releasable -- Release workflow documented in `docs/RELEASE_WORKFLOW.md` - -## Build & Test Commands - -```bash -pnpm install # Install dependencies -pnpm build # Build all extensions -pnpm test:unit # Run unit tests -pnpm test:e2e # Run E2E tests -pnpm lint # Run ESLint -``` - -## Important Constraints - -- **AGPL-3.0 copyleft license:** The OSPO Apache 2.0 migration requires auditing this copyleft license. -- **Monorepo structure:** Each extension in `packages/` can be built and released independently. -- **oCIS dependency:** Extensions require oCIS and ownCloud Web to function. -- **Docker image:** Published as `owncloud/web-extensions` on Docker Hub. -- **External dependencies:** Some extensions (draw.io, external sites) embed or connect to third-party services. - - -## OSPO Policy Constraints - -### GitHub Actions -- **Only** use actions owned by `owncloud`, created by GitHub (`actions/*`), verified on the GitHub Marketplace, or verified by the ownCloud Maintainers. -- Pin all actions to their full commit SHA (not tags): `uses: actions/checkout@ # vX.Y.Z` -- Never introduce actions from unverified third parties. - -### Dependency Management -- Dependabot is configured for automated dependency updates. -- Review and merge Dependabot PRs as part of regular maintenance. -- Do not introduce new dependencies without discussion in an issue first. - -### Git Workflow -- **Rebase policy**: Always rebase; never create merge commits. Use `git pull --rebase` and `git rebase` before pushing. -- **Signed commits**: All commits **must** be PGP/GPG signed (`git commit -S -s`). -- **DCO sign-off**: Every commit needs a `Signed-off-by` line (`git commit -s`). -- **Conventional Commits & Squash Merge**: Use the [Conventional Commits](https://www.conventionalcommits.org/) format where the repository enforces it. Many repos use squash merge, where the PR title becomes the commit message on the default branch — apply Conventional Commits format to PR titles as well. A reusable GitHub Actions workflow enforces this. - -## Context for AI Agents - -- This is a pnpm monorepo containing multiple independent web extensions. -- Each extension in `packages/` has its own `package.json`, source code and build config. -- The `docs/starting_guide.md` explains how to add new extensions to the repository. -- Docker images bundle all extensions together for deployment. -- Extensions register with the oCIS Web runtime via the extension system API. -- Development environment uses Docker Compose with an oCIS backend.