devXY web presence
https://devxy.io
- Astro 73.4%
- XSLT 18.8%
- JavaScript 3.8%
- CSS 1.5%
- HCL 1.2%
- Other 1.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
> **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 |
||
| .crow | ||
| .vscode | ||
| assets | ||
| docs/superpowers | ||
| post-template | ||
| public | ||
| scripts | ||
| src | ||
| src-dev | ||
| .editorconfig | ||
| .gitignore | ||
| .lycheeignore | ||
| .npmrc | ||
| .pre-commit-config.yaml | ||
| .prettierignore | ||
| .prettierrc | ||
| .prettierrc.json | ||
| .terraform.lock.hcl | ||
| astro.config.mjs | ||
| backend.tf | ||
| bun.lock | ||
| bunny.tf | ||
| Justfile | ||
| LICENSE.md | ||
| lychee.toml | ||
| package.json | ||
| provider.tf | ||
| README.md | ||
| renovate.json | ||
| s3.tf | ||
| tsconfig.json | ||
| vars.tf | ||
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
-
Create new markdown file in
src/content/blog/ -
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"] --- -
Write content in Markdown
-
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
- Install via Fontsource:
bun add @fontsource/font-name - Import in
src/layouts/Layout.astro - Configure in
src/styles/theme.css
Deployment
Environment Variables
SITE_URL- Site URL for current environmentUMAMI_ID- Analytics tracking ID
Build Process
- Environment-specific builds set proper analytics and
robots.txt - Static files generated to
/dist - Deployed to AWS S3 + Bunny CDN
- Terraform manages infrastructure
No matching headings