Ctrl K
ComunidadGuías…

AGENTS.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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:** Apache-2.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)
- `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 `<name>` with the package name, e.g. `draw-io`,
`advanced-search`):

```bash
pnpm --filter <name> build
pnpm --filter <name> test:unit
pnpm --filter <name> test:e2e
pnpm --filter <name> 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-<name>/` 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

- **Monorepo structure:** Each extension in `packages/` can be built and released independently.
- **oCIS dependency:** Extensions require oCIS and ownCloud Web to function.
- **Docker image:** Built and published as `owncloud/web-extensions` from [owncloud-docker/web-extensions](https://github.com/owncloud-docker/web-extensions), not from this repository.
- **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@<SHA> # 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.
- Extensions register with the oCIS Web runtime via the extension system API.
- Development environment uses Docker Compose with an oCIS backend.