devxy/web
Watch
0
1
Fork
You've already forked web
0
devXY web presence https://devxy.io
  • Astro 73.4%
  • XSLT 18.8%
  • JavaScript 3.8%
  • CSS 1.5%
  • HCL 1.2%
  • Other 1.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
pat-s 86c3673b10
All checks were successful
ci/crow/push/links Pipeline was successful
ci/crow/push/lint Pipeline was successful
docs(legal): add a data processing agreement for devXY Cloud (#281)
> **Needs legal review before merge.**
> This is legal text drafted from the code, not by a lawyer.

Rebased onto `main` after #280 and #284 merged.

## What changes

- `src/pages/dpa.astro` (new, `/dpa`): a data processing agreement on `LegalLayout` with a section list.
  It covers the Art. 28(3) GDPR elements: subject matter and duration, nature and purpose, types of data and data subjects, documented instructions (and telling the customer when an instruction looks unlawful), confidentiality, security, sub-processors, help with data subject requests and Art. 32 to 36, breach notification, deletion or return, information and audits, and international transfers.
  It also has a Swiss FADP section (Art. 8, 9(1)(a), 9(2), 9(3) and 24(3)), liability, precedence and changes, and a technical and organizational measures section.
  It applies to customer data in hosted applications only; data devXY controls itself (accounts, audit logs, billing) stays in the privacy policy.
- Sub-processors: the DPA links `/privacy#subprocessors` instead of copying it, gives general authorization, promises 30 days' email notice to owners and admins, and lets customers object or terminate.
- `src/pages/terms.astro`: "Scope" and "Your data" now say the DPA forms part of the terms, and link it.
- `src/pages/privacy.astro`: the "on request" sentence is replaced with a link to the DPA, and the sub-processor list points to the DPA for change notices.
- "Last updated" was already 15 November 2026 (today) on all three pages.

## Sources for the technical and organizational measures

Read only, nothing changed in these repos.

- Portal access: saas-portal `lib/auth/options.ts` and README (invite-only, verified email), `db/schema/memberships.ts`, `instance-access.ts`, `org-sso-connections.ts`; admin overrides need a reason and are audited: `lib/cloud/authz.ts` (`requireInstanceOverride`, `requireOverrideReason`).
- Tenant isolation: `control-plane/drivers/kubernetes/tenant/render.ts` (a namespace per instance, `restricted` Pod Security Standard, default-deny NetworkPolicy, ingress from the gateway and monitoring only, Capsule quota) and `objects.ts` (non-root, no privilege escalation, all capabilities dropped, read-only root by default, HTTP-to-HTTPS redirect route).
- Databases: `control-plane/drivers/kubernetes/instance-databases.ts` (own database and role per instance, random 32-byte password, `sslmode=require`); k8s-ceph-fsn1 `apps/portal/postgres-cluster.yaml` (`hostssl sameuser ... scram-sha-256`, all else rejected, `instances: 3`).
- Secrets: `lib/crypto/secret-box.ts` (AES-256-GCM for instance OIDC client secrets and SMTP passwords); k8s-ceph-fsn1 `apps/portal/externalsecrets.yaml` (key from OpenBao via External Secrets).
- Backups: k8s-ceph-fsn1 `apps/portal/postgres-backup.yaml` (WAL archiving and daily base backups to Scaleway `fr-par`); pg-zrh `docs/backup-provider.md` (client-side `aes-256-cbc`, Infomaniak `gva1`, replicated within Switzerland); `control-plane/domain/retention.ts` and k8s-ceph-fsn1 `components/postgres-backup-retention` (35 days).
- Audit logs: `db/schema/audit-logs.ts`, `lib/cloud/audit.ts`, README "Audit retention" (365 days).

Things I left out on purpose because nothing sources them:

- Encryption at rest for live volumes, and client-side encryption of the Germany backups: the Barman `ObjectStore` in k8s-ceph-fsn1 sets compression but no encryption, so the DPA claims encryption only for Switzerland backups and HTTPS for uploads.
- Staff training, incident response processes and data center certifications.
- saas-portal `docs/shared-postgres.md` still says production backs up to B2 with a seven-day window; the deployed config in k8s-ceph-fsn1 says Scaleway, so I followed the infra repo as #280 does. That doc is probably stale.

## Decisions for pat-s

The `{/* DECISION: ... */}` source comments are removed, as in #284, so this list is the only record of them.

1. **Confidentiality of staff**: the DPA says everyone with access is bound by confidentiality, as Art. 28(3)(b) requires. Please confirm the employment and contractor contracts say so.
2. **Sub-processor changes**: 30 days' notice by email to owners and admins, objection on reasonable data protection grounds within that period.
3. **Remedy for an objection**: terminating the affected part of the service, with no cancellation fee, if the objection can't be resolved.
4. **Cost of assistance**: help beyond the service and the DPA is charged at usual rates after a cost estimate; help with a breach caused by devXY is free.
5. **Breach notification deadline**: without undue delay and at the latest within 48 hours, by email to owners and admins. The law only requires "without undue delay" (GDPR) and "as soon as possible" (FADP).
6. **Return of data**: customers export through their applications; no other form is offered.
7. **Deletion deadline**: live data no later than 30 days after cancellation takes effect (the portal only configures the earliest deletion, 14 days), backups within 35 days of being made (sourced).
8. **Audit rights and their cost**: written questions first, 30 days' notice, once a year unless a breach or an authority requires otherwise, business hours, confidential and non-competitor auditor, no access to other customers' data, customer pays devXY's reasonable costs unless the audit finds a material breach.
9. **Liability under the DPA**: subject to the cap in the terms' Liability section, without limiting liability to data subjects under Art. 82 GDPR.
10. **Changes to the DPA**: 30 days' notice as for the terms, sooner where the law requires a change.
11. **Signed copy**: the DPA applies without a signature, as part of the terms, and no signed copy is offered.

The 14-day retention after cancellation is reused from #278 and keeps its decision there.

## Checks

- `bun run build` passes and renders `/dpa`.
- `prek run --files` on the three changed files passes.

1 comments

Reviewed-on: #281
2026-11-15 15:02:45 +00:00
.crow ci: pin build image to node:26-slim (#283) 2026-11-15 13:47:01 +00:00
.vscode initial state 2024-05-20 15:18:39 +02:00
assets add Crow CI workflows, editorconfig, and lychee link checker config 2026-04-13 22:37:14 +02:00
docs/superpowers Add clients section to root page (#85) 2026-09-01 16:06:30 +00:00
post-template docs(blog): announce ForgeGo on the App Store and Google Play (#208) 2026-09-25 11:32:03 +00:00
public docs(blog): announce ForgeGo on the App Store and Google Play (#208) 2026-09-25 11:32:03 +00:00
scripts feat: improve social preview handling 2025-07-10 15:48:49 +02:00
src docs(legal): add a data processing agreement for devXY Cloud (#281) 2026-11-15 15:02:45 +00:00
src-dev refactor: tailwind v4 migration (#21) 2025-05-16 14:56:22 +00:00
.editorconfig fix editorconfig violations and add trivy template and lychee excludes 2026-04-13 22:39:57 +02:00
.gitignore refactor: switch to new deployment model 2025-07-10 22:17:25 +02:00
.lycheeignore add Crow CI workflows, editorconfig, and lychee link checker config 2026-04-13 22:37:14 +02:00
.npmrc fix editorconfig violations and add trivy template and lychee excludes 2026-04-13 22:39:57 +02:00
.pre-commit-config.yaml chore(deps): update pre-commit hook sirosen/texthooks to v1 (#239) 2026-11-01 08:45:23 +00:00
.prettierignore fix editorconfig violations and add trivy template and lychee excludes 2026-04-13 22:39:57 +02:00
.prettierrc initial state 2024-05-20 15:18:39 +02:00
.prettierrc.json prettier 2024-05-20 16:31:39 +02:00
.terraform.lock.hcl chore(deps): update terraform bunnynet to v0.20.2 (#275) 2026-11-14 02:15:01 +00:00
astro.config.mjs fix(deps): update astro monorepo (major) (#84) 2026-07-02 09:38:10 +00:00
backend.tf add bunny tf config 2024-08-11 11:02:04 +02:00
bun.lock chore(deps): lock file maintenance (#255) 2026-11-15 13:44:12 +00:00
bunny.tf refactor: move website hosting to statichost 2025-07-24 15:21:12 +02:00
Justfile fix editorconfig violations and add trivy template and lychee excludes 2026-04-13 22:39:57 +02:00
LICENSE.md initial state 2024-05-20 15:18:39 +02:00
lychee.toml docs(blog): announce ForgeGo on the App Store and Google Play (#208) 2026-09-25 11:32:03 +00:00
package.json fix(deps): update astro monorepo (#267) 2026-11-15 13:40:59 +00:00
provider.tf chore(deps): update terraform bunnynet to ~> 0.20 (#265) 2026-11-04 03:08:25 +00:00
README.md docs(blog): announce ForgeGo on the App Store and Google Play (#208) 2026-09-25 11:32:03 +00:00
renovate.json chore: prettier 2025-07-10 17:10:03 +02:00
s3.tf refactor: move website hosting to statichost 2025-07-24 15:21:12 +02:00
tsconfig.json chore: prettier 2025-07-10 17:10:03 +02:00
vars.tf aws provider 2024-08-30 16:17:40 +02:00

devXY Website

An Astro 5.x static website for devXY, built with TypeScript and Tailwind CSS.

Quick Start

bun install
bun run dev

# Build for production
bun run build

# Preview production build
bun run preview

Content Creation

Adding Blog Posts

  1. Create new markdown file in src/content/blog/

  2. Add frontmatter with required fields:

    ---
    draft: false
    title: "Your Post Title"
    description: "Brief description for SEO"
    slug: "your-post-slug"
    image: "your-image.png"  # Place in src/assets/blog-images/thumbnails/
    imageAlt: "Alt text for image"
    publishDate: 2024-01-01
    category: "your-category"
    categories_rss: ["category1", "category2"]
    tags: ["tag1", "tag2"]
    ---
    
  3. Write content in Markdown

  4. Images are automatically optimized and imported

Adding Images

  • Place images in src/assets/blog-images/thumbnails/
  • Reference by filename only in blog post frontmatter
  • System automatically handles import and optimization

Icons

Add new icon sets:

bun add @iconify-json/<icon-set-name>

Use icons:

<Icon name="mdi:home" />

Find icons at Iconify

Fonts

  1. Install via Fontsource: bun add @fontsource/font-name
  2. Import in src/layouts/Layout.astro
  3. Configure in src/styles/theme.css

Deployment

Environment Variables

  • SITE_URL - Site URL for current environment
  • UMAMI_ID - Analytics tracking ID

Build Process

  1. Environment-specific builds set proper analytics and robots.txt
  2. Static files generated to /dist
  3. Deployed to AWS S3 + Bunny CDN
  4. Terraform manages infrastructure