From 4a5806bf11c5510a2d322f735f283787b96dcc34 Mon Sep 17 00:00:00 2001 From: Ben Fellows Date: Fri, 7 Aug 2026 23:20:38 +1200 Subject: [PATCH] Add teemops.com as a design-partner recruitment page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Self-Hosted Design Partners milestone has been limited by recruitment rather than engineering since 2026-08-01, and there was nowhere to send anyone: teemops.com served nothing. What was in the repo was worse than nothing. design/marketing/web/ held a complete three-page site for a hosted commercial SaaS — Free/Starter/Pro/ Business pricing tiers, "Start Free" CTAs pointing at app.teem.nz/register, a domain that now redirects to an unrelated property — and no mention that TOPS is open source. It contradicted D-1 and D-6 on its face. It is deleted rather than kept as reference, because a second contradictory description of the product is a trap for whoever opens it next. Git history has it. A brand-new page will not generate inbound leads inside the milestone window, so this is built as a conversion asset for outbound rather than a lead engine: one page, stating what TOPS is, proving it is real, saying plainly what it does not do, and making one specific ask. The use-case, compliance and SEO pages from the old content plan are dropped as premature at zero traffic. Every number on the page is checked against the code rather than intent: 74 rules (52 basic + 22 CIS) across 11 services, all carrying a remediation, all 28 critical/high carrying step-by-step guidance. www/README.md records where each is verified. Lead capture is a Worker writing to D1, protected by a honeypot field. Turnstile was built, tested and removed before launch: at five-partner volume a few junk rows are cheaper to skim than a widget is to run, the endpoint sends no email and publishes nothing so spam has no amplification path, and a third-party challenge script that fails to load makes the form unsubmittable and loses a real lead silently. Bot Fight Mode and a rate-limiting rule are the first two responses if spam arrives; Turnstile is the third. Deployment reuses D-13's pattern (Workers static assets), so this adds no new category of infrastructure — one CLI command, one dashboard step, no secrets. Recorded as N-12 and D-14. The roadmap review that preceded this also found it stale in four places, corrected here: N-11's checkboxes were unticked though it shipped, the workstream's "Open — UI" table still listed four closed issues, docs.teemops.com was recorded as not yet connected when it is live and serving, and #109 and #111 appeared nowhere. Co-Authored-By: Claude Opus 5 Signed-off-by: Ben Fellows --- .gitignore | 4 +- design/marketing/web/DEPLOY.md | 36 - design/marketing/web/content-plan.md | 288 -- design/marketing/web/html/features.html | 745 ----- design/marketing/web/html/index.html | 517 --- design/marketing/web/html/logo.png | Bin 97156 -> 0 bytes design/marketing/web/html/pricing.html | 588 ---- design/marketing/web/pages/about.md | 137 - design/marketing/web/pages/compliance.md | 268 -- design/marketing/web/pages/features.md | 333 -- design/marketing/web/pages/homepage.md | 202 -- design/marketing/web/pages/pricing.md | 230 -- design/marketing/web/pages/security.md | 237 -- design/marketing/web/pages/use-cases.md | 326 -- design/marketing/web/pricing-strategy.md | 431 --- design/marketing/web/wireframes/README.md | 138 - design/marketing/web/wireframes/features.md | 256 -- design/marketing/web/wireframes/homepage.md | 342 -- .../web/wireframes/html/features.html | 313 -- .../marketing/web/wireframes/html/index.html | 413 --- .../web/wireframes/html/pricing.html | 155 - .../web/wireframes/html/wireframe.css | 222 -- design/marketing/web/wireframes/pricing.md | 126 - docs/roadmap.md | 179 +- www/.gitignore | 6 + www/README.md | 164 + www/build-assets.py | 121 + www/package-lock.json | 2804 +++++++++++++++++ www/package.json | 28 + www/public/404.html | 30 + www/public/favicon.ico | Bin 0 -> 3485 bytes www/public/index.html | 638 ++++ www/public/logo.png | Bin 0 -> 41486 bytes www/public/og.png | Bin 0 -> 62398 bytes www/public/robots.txt | 5 + www/public/sitemap.xml | 8 + www/src/index.ts | 137 + www/test/signup.test.ts | 153 + www/tsconfig.json | 15 + www/vitest.config.ts | 18 + www/wrangler.jsonc | 37 + 41 files changed, 4318 insertions(+), 6332 deletions(-) delete mode 100644 design/marketing/web/DEPLOY.md delete mode 100644 design/marketing/web/content-plan.md delete mode 100644 design/marketing/web/html/features.html delete mode 100644 design/marketing/web/html/index.html delete mode 100755 design/marketing/web/html/logo.png delete mode 100644 design/marketing/web/html/pricing.html delete mode 100644 design/marketing/web/pages/about.md delete mode 100644 design/marketing/web/pages/compliance.md delete mode 100644 design/marketing/web/pages/features.md delete mode 100644 design/marketing/web/pages/homepage.md delete mode 100644 design/marketing/web/pages/pricing.md delete mode 100644 design/marketing/web/pages/security.md delete mode 100644 design/marketing/web/pages/use-cases.md delete mode 100644 design/marketing/web/pricing-strategy.md delete mode 100644 design/marketing/web/wireframes/README.md delete mode 100644 design/marketing/web/wireframes/features.md delete mode 100644 design/marketing/web/wireframes/homepage.md delete mode 100644 design/marketing/web/wireframes/html/features.html delete mode 100644 design/marketing/web/wireframes/html/index.html delete mode 100644 design/marketing/web/wireframes/html/pricing.html delete mode 100644 design/marketing/web/wireframes/html/wireframe.css delete mode 100644 design/marketing/web/wireframes/pricing.md create mode 100644 www/.gitignore create mode 100644 www/README.md create mode 100644 www/build-assets.py create mode 100644 www/package-lock.json create mode 100644 www/package.json create mode 100644 www/public/404.html create mode 100644 www/public/favicon.ico create mode 100644 www/public/index.html create mode 100644 www/public/logo.png create mode 100644 www/public/og.png create mode 100644 www/public/robots.txt create mode 100644 www/public/sitemap.xml create mode 100644 www/src/index.ts create mode 100644 www/test/signup.test.ts create mode 100644 www/tsconfig.json create mode 100644 www/vitest.config.ts create mode 100644 www/wrangler.jsonc diff --git a/.gitignore b/.gitignore index b00d68c6..3d0a15e3 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,6 @@ references/*/vendor # bind mount, so git ends up unable to modify tracked files the user does not own # ("unable to unlink old ... Permission denied"). Untracking it removes that # whole class of failure. -.aws-sam/ \ No newline at end of file +.aws-sam/ +# Wrangler local state (docs site at repo root, and www/) +.wrangler/ diff --git a/design/marketing/web/DEPLOY.md b/design/marketing/web/DEPLOY.md deleted file mode 100644 index 4262a57c..00000000 --- a/design/marketing/web/DEPLOY.md +++ /dev/null @@ -1,36 +0,0 @@ -# Marketing Site Deployment - -## Quick Deploy - -This is a static site. Deploy the `html/` folder to any static host: -- **S3 + CloudFront** — Upload contents of `html/` to an S3 bucket, configure CloudFront -- **Netlify** — Connect repo, set publish directory to `design/marketing/web/html` -- **Vercel** — Same as Netlify -- **GitHub Pages** — Point to `design/marketing/web/html` -- **Cloudflare Pages** — Connect repo, set build output to `design/marketing/web/html` - -## URLs - -| Link | URL | -|------|-----| -| App | `https://app.teem.nz` | -| Contact | `mailto:hello@teem.nz` | - -Docs link has been removed for now. To add it back, add `https://docs.teem.nz` (or similar) to the nav in index.html, features.html, and pricing.html. - -## File Structure - -``` -html/ -├── index.html # Homepage -├── features.html # Features page -├── pricing.html # Pricing page -└── logo.png # Brand logo — run design/brand/build-teemops-logo.py (transparent PNG) -``` - -## SEO (Optional) - -- Add `sitemap.xml` listing all pages -- Add `robots.txt` -- Add Open Graph meta tags for social sharing -- Add JSON-LD schema (Organization, Product) diff --git a/design/marketing/web/content-plan.md b/design/marketing/web/content-plan.md deleted file mode 100644 index 0412067c..00000000 --- a/design/marketing/web/content-plan.md +++ /dev/null @@ -1,288 +0,0 @@ -# Teemops Marketing Website - Content Plan - -## Overview - -This document outlines all content required for the Teemops marketing website, targeting CTOs and DevOps engineers at SMBs (20-200 employees) in SaaS, Fintech, and Healthtech industries. - ---- - -## Site Structure - -``` -teemops.com/ -├── / (Homepage) -├── /features -├── /pricing -├── /security -├── /docs (links to documentation) -├── /blog (future) -├── /about -├── /contact -├── /login (→ app) -├── /signup (→ app) -│ -├── /use-cases/ -│ ├── /saas-companies -│ ├── /fintech -│ ├── /healthtech -│ └── /agencies -│ -├── /compliance/ -│ ├── /cis-benchmarks -│ ├── /pci-dss -│ └── /soc2 -│ -└── /resources/ (future) - ├── /case-studies - ├── /whitepapers - └── /webinars -``` - ---- - -## Page Requirements - -### 1. Homepage (/) - -**Purpose:** Convert visitors to signups, communicate core value proposition - -**Sections:** -1. Hero - Main value prop + CTA -2. Problem/Pain - Why cloud security is hard -3. Solution - How Teemops helps -4. Features overview - Key capabilities -5. How it works - 3-step process -6. Social proof - Logos, testimonials -7. Pricing teaser - Starting price + CTA -8. Final CTA - Get started - -**Content File:** `pages/homepage.md` -**Mockup:** `html/index.html` - ---- - -### 2. Features Page (/features) - -**Purpose:** Detail all product capabilities for evaluators - -**Sections:** -1. Hero - Features overview -2. AWS Security Scanning -3. Compliance Monitoring (CIS, PCI, SOC2) -4. Multi-Account Management -5. Real-time Alerts -6. Remediation Guidance -7. Reporting & Exports -8. Integrations (future) -9. CTA - -**Content File:** `pages/features.md` -**Mockup:** `html/features.html` - ---- - -### 3. Pricing Page (/pricing) - -**Purpose:** Clear pricing, drive signup decisions - -**Sections:** -1. Pricing tiers (Free, Starter, Pro, Business) -2. Feature comparison table -3. FAQ -4. Enterprise contact CTA - -**Content File:** `pages/pricing.md` -**Mockup:** `html/pricing.html` - ---- - -### 4. Security Page (/security) - -**Purpose:** Build trust, show we practice what we preach - -**Sections:** -1. Our security commitment -2. How we protect your data -3. Compliance certifications (future) -4. Responsible disclosure -5. FAQ - -**Content File:** `pages/security.md` -**Mockup:** `html/security.html` - ---- - -### 5. Use Case Pages (/use-cases/*) - -**Purpose:** Industry-specific messaging and SEO - -**Pages:** -- SaaS Companies -- Fintech & Payments -- Healthtech -- Digital Agencies - -**Content File:** `pages/use-cases.md` -**Mockup:** `html/use-case.html` (template) - ---- - -### 6. Compliance Pages (/compliance/*) - -**Purpose:** Compliance-specific messaging and SEO - -**Pages:** -- CIS AWS Benchmarks -- PCI-DSS -- SOC 2 - -**Content File:** `pages/compliance.md` -**Mockup:** `html/compliance.html` (template) - ---- - -### 7. About Page (/about) - -**Purpose:** Build trust, tell our story - -**Sections:** -1. Our mission -2. The team (future) -3. Why we built Teemops -4. Contact info - -**Content File:** `pages/about.md` - ---- - -### 8. Contact Page (/contact) - -**Purpose:** Lead capture, support inquiries - -**Sections:** -1. Contact form -2. Email addresses -3. Social links - -**Content File:** `pages/contact.md` - ---- - -## Content Inventory - -### Core Messaging - -| Element | Content | -|---------|---------| -| **Tagline** | "AWS Security Scanning Made Simple" | -| **Subheadline** | "Find misconfigurations before attackers do. Get actionable fixes in minutes, not weeks." | -| **Value Prop 1** | See all your AWS security gaps in one dashboard | -| **Value Prop 2** | Continuous CIS, PCI-DSS, SOC 2 compliance monitoring | -| **Value Prop 3** | One-click remediation guidance for every finding | -| **CTA Primary** | "Start Free Scan" | -| **CTA Secondary** | "Book a Demo" | - -### SEO Keywords (Primary) - -| Keyword | Search Volume | Difficulty | Priority | -|---------|---------------|------------|----------| -| AWS security scanning | Medium | Medium | High | -| AWS misconfiguration scanner | Low | Low | High | -| Cloud security posture management | Medium | High | Medium | -| AWS CIS benchmark tool | Low | Low | High | -| AWS compliance monitoring | Medium | Medium | High | -| S3 bucket security checker | Low | Low | High | - -### SEO Keywords (NZ-Specific) - -| Keyword | Priority | -|---------|----------| -| AWS security NZ | High | -| Cloud security New Zealand | High | -| NZISM compliance | Medium | -| NZ Privacy Act compliance | Medium | - ---- - -## Content Assets Required - -### Images/Graphics - -| Asset | Purpose | Status | -|-------|---------|--------| -| Hero illustration | Homepage hero | Needed | -| Feature icons (8x) | Features page | Needed | -| How it works diagram | Homepage | Needed | -| Dashboard screenshot | Social proof | Needed | -| Scan results screenshot | Features | Needed | -| Compliance badges | Trust signals | Needed | -| Team photos | About page | Future | -| Customer logos | Social proof | Future | - -### Videos (Future) - -| Video | Purpose | Priority | -|-------|---------|----------| -| Product demo (2 min) | Homepage, features | High | -| Getting started tutorial | Onboarding | Medium | -| Customer testimonials | Social proof | Medium | - ---- - -## Page Priority for MVP - -| Priority | Page | Reason | -|----------|------|--------| -| 1 | Homepage | Core conversion page | -| 2 | Pricing | Required for purchase decisions | -| 3 | Features | Evaluator research | -| 4 | Security | Trust building | -| 5 | Use Cases (SaaS) | Target market alignment | -| 6 | Compliance (CIS) | SEO + credibility | -| 7 | About | Trust building | -| 8 | Contact | Lead capture | - ---- - -## Technical Requirements - -### Performance -- Page load < 3 seconds -- Mobile-first responsive design -- Core Web Vitals optimized - -### SEO -- Meta titles/descriptions for all pages -- Open Graph tags -- Schema markup (Organization, Product, FAQ) -- Sitemap.xml -- robots.txt - -### Analytics -- Google Analytics 4 -- Conversion tracking (signup, demo request) -- Heatmaps (Hotjar/similar) - -### Integration -- CTA buttons link to app signup -- Contact form to CRM/email -- Chat widget (future - Intercom/Crisp) - ---- - -## Content Timeline - -| Week | Deliverable | -|------|-------------| -| 1 | Homepage copy + mockup | -| 1 | Pricing page copy + mockup | -| 2 | Features page copy + mockup | -| 2 | Security page copy | -| 3 | Use case pages (2) | -| 3 | Compliance pages (1) | -| 4 | About, Contact pages | -| 4 | Final review + polish | - ---- - -*Last updated: January 2026* diff --git a/design/marketing/web/html/features.html b/design/marketing/web/html/features.html deleted file mode 100644 index fa2e62a7..00000000 --- a/design/marketing/web/html/features.html +++ /dev/null @@ -1,745 +0,0 @@ - - - - - - Features - AWS Security Scanning & Compliance | Teemops - - - - - - - - - - -
-
-

Complete AWS Security Visibility

-

- Built in New Zealand. Scan your entire AWS environment—find misconfigurations and fix them fast. -

- - Start Free Scan → - -
-
- - -
-
-
-

Comprehensive AWS Coverage

-

Security scanning across your most critical AWS services

-
- -
- -
-
- - - -
-

S3 - Object Storage

-
    -
  • • Public bucket detection
  • -
  • • Encryption verification
  • -
  • • Bucket policy analysis
  • -
  • • Access logging status
  • -
  • • Versioning config
  • -
-
- - -
-
- - - -
-

IAM - Identity & Access

-
    -
  • • Root account security
  • -
  • • MFA enforcement
  • -
  • • Password policy
  • -
  • • Access key rotation
  • -
  • • Overly permissive policies
  • -
-
- - -
-
- - - -
-

EC2 & VPC - Network

-
    -
  • • Security group analysis
  • -
  • • Public IP exposure
  • -
  • • IMDSv2 enforcement
  • -
  • • VPC flow logs
  • -
  • • Network ACL review
  • -
-
- - -
-
- - - -
-

RDS - Databases

-
    -
  • • Public accessibility
  • -
  • • Encryption status
  • -
  • • Backup configuration
  • -
  • • Multi-AZ deployment
  • -
  • • Security group rules
  • -
-
-
- - -
-

Coming Soon

-
- CloudTrail - Lambda - KMS - Secrets Manager - EKS/ECS -
-
-
-
- - -
-
-
-
- Compliance Monitoring -

Compliance-First Security

-

- Our rules align with CIS AWS Foundations Benchmark. PCI-DSS and SOC 2 mapping are on our roadmap. Know your compliance posture—not just before audits. -

- -
-
-
- CIS -
-
-

CIS AWS Foundations Benchmark

-

Rules aligned with CIS controls across IAM, S3, EC2, RDS

-
-
-
-
- PCI -
-
-

PCI-DSS

-

Roadmap: Payment card industry requirements

-
-
-
-
- SOC -
-
-

SOC 2

-

Roadmap: Trust Service Criteria mapping

-
-
-
-
- -
- -
-

Compliance Dashboard

- Last scan: 2 hours ago -
-
-
-
- CIS AWS Benchmark v5.0 - 82% -
-
-
-
-
-
-
- PCI-DSS v4.0 - 68% -
-
-
-
-
-
-
- SOC 2 - 91% -
-
-
-
-
-
-
-
-
32
-
Passing
-
-
-
6
-
Warning
-
-
-
2
-
Failing
-
-
-
-
-
-
- - -
-
-
-
- -
-
-
-
-
- P -
-
-
Production
-
AWS: 123456789012
-
-
-
-
-
92
-
Score
-
- Healthy -
-
-
-
-
- S -
-
-
Staging
-
AWS: 234567890123
-
-
-
-
-
74
-
Score
-
- 3 Issues -
-
-
-
-
- D -
-
-
Development
-
AWS: 345678901234
-
-
-
-
-
58
-
Score
-
- 8 Issues -
-
-
-
-
- -
- Multi-Account Management -

One Dashboard for All Your AWS Accounts

-

- Whether you have 2 accounts or 200, see your security posture across your entire AWS footprint in a single view. -

- -
    -
  • - - - -
    - Centralized Dashboard -

    Aggregate findings from all accounts

    -
    -
  • -
  • - - - -
    - Organization Grouping -

    Group accounts by team, environment, or client

    -
    -
  • -
  • - - - -
    - Cross-Account Trends -

    Compare security posture across accounts

    -
    -
  • -
-
-
-
-
- - -
-
-
-
- Actionable Remediation -

Don't Just Find Problems—Fix Them

-

- Every finding includes clear, actionable remediation guidance. No security expertise required. -

- -
-
-
- - - -
-
-

Plain English Explanations

-

Understand why each finding matters and the actual risk

-
-
-
-
- - - -
-
-

Step-by-Step Instructions

-

Detailed remediation steps anyone can follow

-
-
-
-
- - - -
-
-

Copy-Paste Commands

-

AWS CLI commands ready to execute

-
-
-
-
- -
- -
-
- Critical - IAM -
-
-

Root Account Has Active Access Keys

-

- The AWS root account has access keys enabled. Root access keys provide unrestricted access to all resources and should never be used for day-to-day operations. -

- -
-

Risk

-

If compromised, attackers gain complete control over your AWS account with no audit trail of root actions.

-
- -
-

How to fix:

-
    -
  1. Sign in to AWS Console as root user
  2. -
  3. Navigate to IAM → Security credentials
  4. -
  5. Delete all access keys for root account
  6. -
  7. Create IAM users with appropriate permissions instead
  8. -
-
- -
- -
-
-
-
-
-
-
- - -
-
-
- Risk Prioritization -

Focus on What Actually Matters

-

Not all findings are equal. We prioritize by real-world risk.

-
- -
-
-
-
-

Critical

-
-

Actively exploitable. Immediate action required.

-

Example: S3 bucket publicly writable

-
-
-
-
-

High

-
-

Significant risk. Fix within days.

-

Example: Root account without MFA

-
-
-
-
-

Medium

-
-

Moderate risk. Plan remediation.

-

Example: Access keys not rotated 90+ days

-
-
-
-
-

Low

-
-

Minor risk or best practice.

-

Example: CloudTrail not in unused region

-
-
- -
-

Smart Prioritization Considers:

-
-
-
- - - -
-

Exploitability

-

How easy to attack

-
-
-
- - - -
-

Impact

-

Potential damage

-
-
-
- - - -
-

Exposure

-

Public vs internal

-
-
-
- - - -
-

Compliance

-

Regulatory requirements

-
-
-
-
-
- - -
-
-
- -
- Alerts & Notifications -

Know Immediately When Issues Arise

-

- Get notified the moment critical security issues are detected. Never miss a misconfiguration. -

- -
-
-
- - - -
-
-

Email

-

Instant alerts for critical findings

-
-
-
-
- # -
-
-

Slack

-

Direct to your team's channel

-
-
-
-
- - - -
-
-

Webhooks

-

Integrate with any system

-
-
-
-
- - -
- Reporting & Exports -

Reports Your Auditors Will Love

-

- Generate professional reports for compliance audits, board meetings, or internal reviews. -

- -
-

Report Types

-
-
- Executive Summary - PDF -
-
- CIS Benchmark Report - PDF, CSV -
-
- PCI-DSS Compliance - PDF, CSV -
-
- Technical Details - JSON, CSV -
-
-
-
-
-
-
- - -
-
- Easy Setup -

Secure in Minutes, Not Months

-

No agents to install. No complex configuration.

- -
-
-
1
-

Create Account

-

Sign up with email or OAuth

-
-
-
2
-

Connect AWS

-

One-click CloudFormation (2 min)

-
-
-
3
-

See Results

-

Automatic scan with findings

-
-
- -
-

Security Guarantee

-
- - - - - Read-only access only - - - - - - No credentials stored - - - - - - Revoke anytime - -
-
-
-
- - -
-
-

See All Your AWS Security Gaps

-

- Start your first scan in under 5 minutes. Free tier available. -

- -
-
- - - - - - diff --git a/design/marketing/web/html/index.html b/design/marketing/web/html/index.html deleted file mode 100644 index b76be894..00000000 --- a/design/marketing/web/html/index.html +++ /dev/null @@ -1,517 +0,0 @@ - - - - - - Teemops - AWS Security Scanning Made Simple - - - - - - - - - - -
-
-
-
-

- AWS Security Scanning Made Simple -

-

- Built in New Zealand. Find misconfigurations before attackers do—get actionable fixes in minutes, not weeks. -

- -

No credit card required. Free tier available forever.

-
- -
-
-
- - -
-
-
-

Your AWS Account Is Probably Exposed Right Now

-

- Most cloud breaches aren't sophisticated attacks. They're simple misconfigurations. -

-
-
-
-
- - - -
-

Public S3 Buckets

-

Leaking customer data to the internet

-
-
-
- - - -
-

Overly Permissive IAM

-

Wildcard policies granting excessive access

-
-
-
- - - -
-

Open Security Groups

-

SSH and RDP accessible from anywhere

-
-
-
- - - -
-

Unencrypted Databases

-

Sensitive data stored without encryption

-
-
-
-

- You're one misconfiguration away from a headline you don't want. -

-

- The average data breach costs $4.45 million. For SMBs, it can mean the end. -

-
-
-
- - -
-
-
-
-

- Know Exactly What's Wrong—And How to Fix It -

-

- Teemops continuously scans your AWS accounts and tells you: -

-
-
-
- 1 -
-
-

What's misconfigured

-

In plain English, not AWS jargon

-
-
-
-
- 2 -
-
-

How severe it is

-

Prioritized by actual risk, not noise

-
-
-
-
- 3 -
-
-

How to fix it

-

Step-by-step remediation for every finding

-
-
-
-

- No security team required. No 80-page audit reports. Just clarity. -

-
-
- -
-
- Critical - S3 -
-
-

S3 Bucket Publicly Accessible

-

- Bucket "prod-customer-data" allows public read access. Anyone on the internet can view its contents. -

-
-

How to fix:

- - aws s3api put-public-access-block --bucket prod-customer-data --public-access-block-configuration ... - -
- -
-
-
-
-
-
- - -
-
-
-

Everything You Need to Secure AWS

-

For CTOs and DevOps teams at SaaS, fintech, and healthtech companies

-
-
-
-
- - - -
-

Continuous Scanning

-

Daily automated scans across S3, IAM, EC2, RDS, and more.

-
-
-
- - - -
-

Compliance Monitoring

-

CIS-focused rules today. PCI-DSS and SOC 2 alignment on the roadmap.

-
-
-
- - - -
-

Multi-Account Dashboard

-

See all your AWS accounts in one unified view.

-
-
-
- - - -
-

Actionable Remediation

-

CLI commands and CloudFormation for every finding.

-
-
-
- - - -
-

Risk Prioritization

-

Focus on critical issues first, not compliance noise.

-
-
-
- - - -
-

Instant Alerts

-

Slack, email, or webhook notifications on critical issues.

-
-
- -
-
- - -
-
-
-

Secure Your AWS in 3 Steps

-

Get started in under 5 minutes

-
-
-
-
1
-

Connect Your AWS Account

-

One-click CloudFormation setup. Read-only access—we never modify your resources.

-

Time: 2 minutes

-
-
-
2
-

Run Your First Scan

-

We scan your entire AWS environment against 25+ security checks across S3, IAM, EC2, and RDS.

-

Time: 5 minutes

-
-
-
3
-

Fix What Matters

-

See prioritized findings with clear remediation steps.

-

Time: You decide

-
-
- -
-
- - -
-
-
-

Built in New Zealand for Growing Tech Teams

-

Join teams across NZ and beyond securing their AWS environments—SaaS, fintech, and healthtech.

-
-
-
-
4
-
AWS services scanned
-
-
-
25+
-
Security checks
-
-
-
S3
-
IAM • EC2 • RDS
-
-
-
< 5 min
-
Time to first scan
-
-
- -

What teams securing AWS are saying

-
-
-

- "We knew we had security gaps but didn't know where to start. Teemops showed us exactly what to fix first. Saved us from hiring a consultant." -

-
-
-
-
CTO
-
NZ SaaS Company (50 employees)
-
-
-
-
-

- "The compliance reporting alone is worth it. Our auditors love the CIS benchmark reports." -

-
-
-
-
VP Engineering
-
Fintech Startup
-
-
-
-
-
-
- - -
-
-

Start Free. Scale When Ready.

-

- Free for 1 AWS account. Paid plans from $99/month. -

-

No credit card required. Cancel anytime.

- See Pricing → -
-
- - -
-
-

Stop Guessing. Start Knowing.

-

- See your AWS security posture in the next 5 minutes. -

- -
-
- - - - - - diff --git a/design/marketing/web/html/logo.png b/design/marketing/web/html/logo.png deleted file mode 100755 index 5c7053c1e2579ab4d4e74680f9480f0b4c8e7899..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97156 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 diff --git a/design/marketing/web/html/pricing.html b/design/marketing/web/html/pricing.html deleted file mode 100644 index f5dc7f26..00000000 --- a/design/marketing/web/html/pricing.html +++ /dev/null @@ -1,588 +0,0 @@ - - - - - - Pricing - Teemops AWS Security Scanning - - - - - - - -

- - -
-
-

Simple Pricing. No Surprises.

-

Built in New Zealand. Start free. Upgrade when you're ready. Cancel anytime.

- - -
- Monthly - - Annual - Save 20% -
-
-
- - -
-
-
- - -
-

Free

-

Perfect for getting started

-
- $0 - /month -
- - Get Started Free - -
    -
  • - - - - 1 AWS account -
  • -
  • - - - - Weekly scans -
  • -
  • - - - - 25+ security checks -
  • -
  • - - - - Email alerts -
  • -
  • - - - - 7-day history -
  • -
  • - - - - Community support -
  • -
-
- - -
-

Starter

-

For small teams and startups

-
- $99 - /month -
- - Start 14-Day Trial - -
    -
  • - - - - Up to 3 AWS accounts -
  • -
  • - - - - Daily scans -
  • -
  • - - - - 25+ security checks (expanding) -
  • -
  • - - - - CIS Benchmark reports -
  • -
  • - - - - Email + Slack alerts -
  • -
  • - - - - 30-day history -
  • -
  • - - - - Email support -
  • -
-
- - -
-
- Most Popular -
-

Pro

-

For growing companies

-
- $299 - /month -
- - Start 14-Day Trial - -

Everything in Starter, plus:

-
    -
  • - - - - Up to 10 AWS accounts -
  • -
  • - - - - Hourly scan scheduling -
  • -
  • - - - - PCI-DSS reports -
  • -
  • - - - - SOC 2 reports -
  • -
  • - - - - API access -
  • -
  • - - - - 90-day history -
  • -
  • - - - - Priority support -
  • -
-
- - -
-

Business

-

For larger organizations

-
- Custom -
- - Contact Sales - -

Everything in Pro, plus:

-
    -
  • - - - - Unlimited AWS accounts -
  • -
  • - - - - Real-time continuous scanning -
  • -
  • - - - - Custom compliance frameworks -
  • -
  • - - - - SSO/SAML integration -
  • -
  • - - - - Dedicated account manager -
  • -
  • - - - - SLA guarantee -
  • -
  • - - - - Phone support -
  • -
-
-
-
-
- - -
-
-

Compare Plans

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FeatureFreeStarterProBusiness
AWS Accounts1310Unlimited
Scan FrequencyWeeklyDailyHourlyReal-time
Security Checks25+25+ (expanding)25+ (expanding)25+ (expanding)
CIS BenchmarksBasic
PCI-DSS Reports
SOC 2 Reports
Slack Integration
API Access
Finding History7 days30 days90 daysUnlimited
Team Members1515Unlimited
SSO/SAML
SupportCommunityEmailPriorityDedicated
-
-
-
- - -
-
-

Frequently Asked Questions

-
-
- - Do I need a credit card to start? - - - - -

- No. The free tier requires no credit card. We only ask for payment when you upgrade to a paid plan. -

-
- -
- - Can I change plans anytime? - - - - -

- Yes. Upgrade, downgrade, or cancel at any time. Changes take effect immediately, and we prorate any differences. -

-
- -
- - What AWS permissions do you need? - - - - -

- We use a read-only IAM role. We never modify, delete, or create resources in your AWS account. See our Security page for details. -

-
- -
- - Is there a discount for startups or non-profits? - - - - -

- Yes. We offer 50% off for early-stage startups (under $1M funding) and registered non-profits. Contact us to apply. -

-
- -
- - Can I get a refund? - - - - -

- We offer a 14-day money-back guarantee on all paid plans. No questions asked. -

-
-
-
-
- - -
-
-

Need More?

-

- For organizations with complex requirements, custom integrations, or regulatory needs—let's talk. -

-
- • Unlimited AWS accounts - • Custom compliance frameworks - • Dedicated support - • Volume discounts -
- - Contact Sales - -
-
- - -
-
-

Start Securing Your AWS Today

-

No credit card required. Free tier available forever.

- - Get Started Free - -
-
- - - - - - - - diff --git a/design/marketing/web/pages/about.md b/design/marketing/web/pages/about.md deleted file mode 100644 index f4163f51..00000000 --- a/design/marketing/web/pages/about.md +++ /dev/null @@ -1,137 +0,0 @@ -# About Page Content - -## Meta Information - -``` -Title: About Teemops - AWS Security Made Simple -Description: Learn about Teemops, our mission to make cloud security accessible for growing tech companies, and the team behind the platform. -``` - ---- - -## Hero Section - -### Headline -**Making Cloud Security Accessible** - -### Subheadline -We believe every company deserves enterprise-grade security visibility—regardless of size or budget. - ---- - -## Our Story - -### Headline -**Why We Built Teemops** - -### Body - -We've been there. - -Running a growing tech company. Shipping features. Scaling infrastructure. Knowing that security matters but never having time to properly address it. - -We'd spin up AWS resources, configure them quickly, and move on. Somewhere in the back of our minds, we knew there were probably misconfigurations. Public S3 buckets. Overly permissive IAM roles. Security groups that were "temporary" but never got fixed. - -Then one day, a near-miss. A publicly accessible database that shouldn't have been. Thankfully caught before any damage. But it was a wake-up call. - -We looked for tools to help. What we found was either: -- **Too expensive** — Enterprise CSPM tools costing $50k+/year -- **Too complex** — Requiring dedicated security teams to operate -- **Too noisy** — Hundreds of alerts with no clear prioritization -- **Too basic** — AWS Security Hub telling us problems exist, but not how to fix them - -So we built what we wished existed: **A security tool that tells you exactly what's wrong with your AWS account and exactly how to fix it.** No security degree required. No enterprise budget needed. - -That's Teemops. - ---- - -## Our Mission - -### Headline -**Security Should Be Simple** - -### Body - -We're on a mission to make cloud security accessible to every tech company—not just those with dedicated security teams and enterprise budgets. - -**We believe:** - -- Every CTO should know their security posture at all times -- Every finding should come with actionable remediation -- Security tools should be clear, not confusing -- Compliance shouldn't require consultants -- Good security is achievable for companies of any size - ---- - -## What We Stand For - -### Values - -**Clarity Over Complexity** -We translate security jargon into plain English. If a non-security person can't understand a finding, we rewrite it. - -**Action Over Alerts** -Every alert includes exactly what to do about it. No alert without a solution. - -**Honesty Over Hype** -We won't tell you you're secure when you're not. We won't create FUD to sell more licenses. We tell you the truth about your security posture. - -**Customers Over Revenue** -We'd rather you be secure on our free tier than insecure on a competitor's paid plan. - ---- - -## The Team - -### Headline -**Built by People Who Get It** - -### Body - -We're a small team of engineers and security practitioners who've spent years building and securing cloud infrastructure at scale. - -*[Team photos and bios will go here]* - -**Interested in joining?** We're always looking for people who care about making security accessible. [Contact us](/contact) - ---- - -## Our Location - -### Headline -**Proudly New Zealand Made** - -### Body - -Teemops is built in Wellington, New Zealand. We're part of the vibrant NZ tech community and proud to be building from Aotearoa. - -We serve customers globally, with a particular focus on the APAC region. - ---- - -## Contact - -### Headline -**Get in Touch** - -**General Inquiries:** hello@teemops.com - -**Sales:** sales@teemops.com - -**Security:** security@teemops.com - -**Support:** support@teemops.com - -Or visit our [Contact page](/contact) for more options. - ---- - -## CTA Section - -### Headline -**Ready to See Your Security Posture?** - -### CTA -**Start Free Scan →** diff --git a/design/marketing/web/pages/compliance.md b/design/marketing/web/pages/compliance.md deleted file mode 100644 index eea9454e..00000000 --- a/design/marketing/web/pages/compliance.md +++ /dev/null @@ -1,268 +0,0 @@ -# Compliance Pages Content - ---- - -## CIS AWS Benchmarks (/compliance/cis-benchmarks) - -### Meta Information -``` -Title: CIS AWS Foundations Benchmark Scanning | Teemops -Description: Automated CIS AWS Foundations Benchmark v5.0 compliance scanning. Check all 40+ controls and get audit-ready reports. -``` - -### Hero Section - -**Headline:** CIS AWS Foundations Benchmark Compliance - -**Subheadline:** Automated scanning against all CIS controls. Know your compliance score in minutes. - -**CTA:** Start Free Scan - ---- - -### What is CIS AWS Foundations Benchmark? - -The CIS (Center for Internet Security) AWS Foundations Benchmark is the industry standard for securing AWS accounts. It provides prescriptive guidance for configuring security options across AWS services. - -**Current Version:** v5.0.0 (2024) - -**Why It Matters:** -- Required by many compliance frameworks -- Expected by enterprise customers -- Best practice baseline for AWS security -- Commonly referenced in audits - ---- - -### CIS Sections We Cover - -| Section | Controls | Description | -|---------|----------|-------------| -| 1. IAM | 22 controls | Identity and access management | -| 2. Storage | 8 controls | S3 bucket security | -| 3. Logging | 6 controls | CloudTrail and logging | -| 4. Monitoring | 15 controls | CloudWatch alarms | -| 5. Networking | 6 controls | VPC and network security | - -**Total: 40+ automated checks** - ---- - -### Key CIS Controls We Check - -**Identity & Access Management (Section 1)** -- 1.4: Root account MFA enabled -- 1.5: Root account has no access keys -- 1.8: IAM password policy requirements -- 1.12: No credentials unused for 45+ days -- 1.16: IAM policies attached to groups, not users - -**Storage (Section 2)** -- 2.1.1: S3 Block Public Access enabled -- 2.1.2: S3 buckets encrypted -- 2.1.4: S3 buckets have lifecycle policies - -**Logging (Section 3)** -- 3.1: CloudTrail enabled in all regions -- 3.2: CloudTrail log file validation enabled -- 3.4: CloudTrail logs encrypted - -**Networking (Section 5)** -- 5.1: No unrestricted SSH access -- 5.2: No unrestricted RDP access -- 5.3: VPC flow logging enabled - ---- - -### CIS Compliance Report - -Generate a comprehensive CIS Benchmark report including: - -- **Overall compliance score** — Percentage of controls passing -- **Section-by-section breakdown** — Score per CIS section -- **Individual control status** — Pass/Fail for each control -- **Evidence** — Configuration details for auditors -- **Remediation guidance** — How to fix failing controls - -**Export formats:** PDF, CSV, JSON - ---- - -### CTA Section - -**Headline:** Check Your CIS Compliance Now - -**Body:** See how your AWS account scores against CIS Benchmarks. Takes 5 minutes. - -**CTA:** Start Free Scan - ---- ---- - -## PCI-DSS Compliance (/compliance/pci-dss) - -### Meta Information -``` -Title: PCI-DSS AWS Compliance Scanning | Teemops -Description: Automated PCI-DSS compliance checks for AWS. Verify encryption, access controls, and logging requirements. -``` - -### Hero Section - -**Headline:** PCI-DSS Compliance for AWS - -**Subheadline:** Handle payment data on AWS? Verify your PCI-DSS controls are in place. - -**CTA:** Start Free Scan - ---- - -### What is PCI-DSS? - -The Payment Card Industry Data Security Standard (PCI-DSS) is required for any organization that handles credit card data. Version 4.0 is the current standard. - -**Who Needs PCI Compliance:** -- Payment processors -- E-commerce platforms -- SaaS handling payment info -- Anyone storing/transmitting card data - ---- - -### PCI-DSS Requirements We Check - -**Requirement 1: Network Security** -- Security group configurations -- Network segmentation -- Firewall rules - -**Requirement 3: Protect Stored Data** -- S3 encryption at rest -- RDS encryption -- EBS volume encryption -- Key management - -**Requirement 7: Restrict Access** -- IAM policies and permissions -- Least privilege verification -- Access review - -**Requirement 8: Identify Users** -- MFA enforcement -- Password policies -- Credential management - -**Requirement 10: Track Access** -- CloudTrail logging -- Access logging enabled -- Log retention - -**Requirement 11: Test Security** -- Vulnerability identification -- Configuration review - ---- - -### PCI Compliance Report - -Our PCI-DSS report maps findings directly to PCI requirements: - -| Requirement | Status | Findings | Details | -|-------------|--------|----------|---------| -| Req. 1 | ⚠️ Partial | 3 | SG allows 0.0.0.0/0 | -| Req. 3 | ✅ Pass | 0 | All storage encrypted | -| Req. 7 | ❌ Fail | 5 | IAM policies too broad | -| ... | ... | ... | ... | - ---- - -### CTA Section - -**Headline:** Verify Your PCI Controls - -**Body:** Don't wait for your QSA to find issues. Find them first. - -**CTA:** Start Free Scan - ---- ---- - -## SOC 2 Compliance (/compliance/soc2) - -### Meta Information -``` -Title: SOC 2 AWS Compliance Monitoring | Teemops -Description: Continuous SOC 2 compliance monitoring for AWS. Map security findings to Trust Service Criteria. -``` - -### Hero Section - -**Headline:** SOC 2 Compliance Made Easier - -**Subheadline:** Map your AWS security controls to SOC 2 Trust Service Criteria automatically. - -**CTA:** Start Free Scan - ---- - -### What is SOC 2? - -SOC 2 (Service Organization Control 2) is a compliance framework for service providers storing customer data. It's based on five Trust Service Criteria: - -1. **Security** — Protection against unauthorized access -2. **Availability** — System availability for operation -3. **Processing Integrity** — System processing is complete and accurate -4. **Confidentiality** — Data designated as confidential is protected -5. **Privacy** — Personal information is collected and used appropriately - -**Who Needs SOC 2:** -- SaaS companies -- Cloud service providers -- Data processors -- Any company with enterprise customers - ---- - -### SOC 2 Controls We Check - -**Security (CC6)** -- Access control configuration -- Network security -- Encryption controls -- Authentication settings - -**Availability (A1)** -- Multi-AZ deployments -- Backup configurations -- Disaster recovery readiness - -**Confidentiality (C1)** -- Data encryption -- Access restrictions -- Data classification controls - -**Change Management (CC8)** -- Audit logging -- Configuration tracking -- Access to production systems - ---- - -### SOC 2 Evidence Collection - -Our reports help you gather evidence for SOC 2 audits: - -- **Point-in-time snapshots** — Show control status at audit time -- **Historical trends** — Demonstrate continuous compliance -- **Configuration evidence** — Actual AWS settings -- **Remediation history** — Show issues found and fixed - ---- - -### CTA Section - -**Headline:** Prepare for Your SOC 2 Audit - -**Body:** Know your compliance gaps before your auditor does. - -**CTA:** Start Free Scan diff --git a/design/marketing/web/pages/features.md b/design/marketing/web/pages/features.md deleted file mode 100644 index 16ae5330..00000000 --- a/design/marketing/web/pages/features.md +++ /dev/null @@ -1,333 +0,0 @@ -# Features Page Content - -## Meta Information - -``` -Title: Features - AWS Security Scanning & Compliance | Teemops -Description: Comprehensive AWS security scanning with CIS, PCI-DSS, SOC 2 compliance. Scan S3, IAM, EC2, RDS and more. Actionable remediation for every finding. -Keywords: AWS security features, cloud security scanning, CIS benchmarks, AWS compliance, S3 security, IAM security -``` - ---- - -## Hero Section - -### Headline -**Complete AWS Security Visibility** - -### Subheadline -Scan your entire AWS environment. Find misconfigurations. Fix them fast. - -### CTA -**Start Free Scan →** - ---- - -## Feature Sections - -### 1. AWS Security Scanning - -#### Headline -**Comprehensive AWS Coverage** - -#### Body -Teemops scans your most critical AWS services for security misconfigurations, vulnerabilities, and compliance violations. - -#### Services Covered - -**S3 - Object Storage** -- Public bucket detection -- Encryption at rest verification -- Bucket policy analysis -- Access logging status -- Versioning configuration - -**IAM - Identity & Access** -- Root account security -- MFA enforcement -- Password policy compliance -- Access key rotation -- Overly permissive policies -- Unused credentials detection - -**EC2 & VPC - Compute & Network** -- Security group analysis -- Public IP exposure -- IMDSv2 enforcement -- VPC flow logs -- Network ACL review - -**RDS - Databases** -- Public accessibility -- Encryption status -- Backup configuration -- Multi-AZ deployment -- Security group rules - -**Coming Soon** -- CloudTrail audit logging -- Lambda serverless security -- KMS key management -- Secrets Manager -- EKS/ECS containers - ---- - -### 2. Compliance Monitoring - -#### Headline -**Stay Compliant, Automatically** - -#### Body -Continuous compliance monitoring against industry standards. Know your compliance score at all times—not just before audits. - -#### Compliance Frameworks - -**CIS AWS Foundations Benchmark** -- 40+ controls across all CIS sections -- Automated scoring -- Detailed remediation steps -- Export-ready reports for auditors - -**PCI-DSS** -- Payment card industry requirements -- Network security controls -- Access management checks -- Encryption verification - -**SOC 2** -- Security controls mapping -- Availability requirements -- Confidentiality checks -- Privacy controls - -**Coming Soon** -- ISO 27001 -- HIPAA -- NZISM (NZ Information Security Manual) -- Custom frameworks - -#### Compliance Dashboard -Real-time compliance percentage across all frameworks. Track improvement over time. - ---- - -### 3. Multi-Account Management - -#### Headline -**One Dashboard for All Your AWS Accounts** - -#### Body -Whether you have 2 accounts or 200, see your security posture across your entire AWS footprint in a single view. - -#### Capabilities - -- **Centralized Dashboard** — Aggregate findings from all accounts -- **Per-Account Views** — Drill down into individual accounts -- **Organization Grouping** — Group accounts by team, environment, or client -- **Cross-Account Trends** — Compare security posture across accounts -- **Bulk Operations** — Run scans across multiple accounts at once - -#### Use Cases -- **Agencies** — Manage client AWS accounts separately -- **Multi-Product Companies** — Isolate production, staging, dev -- **Enterprises** — Central visibility across business units - ---- - -### 4. Actionable Remediation - -#### Headline -**Don't Just Find Problems—Fix Them** - -#### Body -Every finding includes clear, actionable remediation guidance. No security expertise required. - -#### What You Get - -**Plain English Explanations** -Understand why each finding matters and what the actual risk is—not just compliance jargon. - -**Step-by-Step Instructions** -Detailed remediation steps anyone on your team can follow. - -**Copy-Paste Commands** -AWS CLI commands ready to execute. Fix issues in seconds. - -**CloudFormation Templates** -Infrastructure-as-code snippets for automated remediation. - -**Documentation Links** -Direct links to relevant AWS documentation for deeper context. - ---- - -### 5. Risk Prioritization - -#### Headline -**Focus on What Actually Matters** - -#### Body -Not all findings are equal. We prioritize by real-world risk so you fix critical issues first. - -#### Severity Levels - -**Critical** (Red) -Actively exploitable. Immediate action required. -*Example: S3 bucket publicly writable* - -**High** (Orange) -Significant risk. Fix within days. -*Example: Root account without MFA* - -**Medium** (Yellow) -Moderate risk. Plan remediation. -*Example: Access keys not rotated in 90+ days* - -**Low** (Blue) -Minor risk or best practice. -*Example: CloudTrail not enabled in unused region* - -**Info** (Gray) -Informational. No action required. -*Example: Resource inventory data* - -#### Smart Prioritization -We consider: -- Exploitability (how easy to attack) -- Impact (what damage could occur) -- Exposure (public vs internal) -- Compliance requirements - ---- - -### 6. Alerts & Notifications - -#### Headline -**Know Immediately When Issues Arise** - -#### Body -Get notified the moment critical security issues are detected. Never miss a misconfiguration. - -#### Channels - -**Email** -Instant email alerts for critical and high severity findings. - -**Slack** -Direct to your team's Slack channel. Configurable by severity. - -**Webhooks** -Integrate with any system—PagerDuty, Jira, custom workflows. - -#### Alert Configuration -- Set severity thresholds -- Configure quiet hours -- Route alerts by AWS account -- Aggregate or individual notifications - ---- - -### 7. Reporting & Exports - -#### Headline -**Reports Your Auditors Will Love** - -#### Body -Generate professional reports for compliance audits, board meetings, or internal reviews. - -#### Report Types - -**Executive Summary** -High-level security posture overview. Perfect for leadership. - -**Compliance Reports** -Framework-specific reports (CIS, PCI-DSS, SOC 2) with pass/fail status. - -**Technical Detail** -Full finding details for engineering teams. - -**Trend Reports** -Security posture over time. Show improvement. - -#### Export Formats -- PDF (formatted reports) -- CSV (raw data) -- JSON (API integration) - ---- - -### 8. Easy Setup - -#### Headline -**Secure in Minutes, Not Months** - -#### Body -No agents to install. No complex configuration. Connect your AWS account in under 5 minutes. - -#### How It Works - -**Step 1: Create Account** -Sign up with email or Google/GitHub OAuth. - -**Step 2: Connect AWS** -One-click CloudFormation template creates a read-only IAM role. - -**Step 3: Scan** -We automatically scan your environment and show results. - -#### Security -- Read-only access only -- No credentials stored -- IAM role with least privilege -- Audit trail of all access - ---- - -## Feature Comparison - -### Headline -**Teemops vs. The Alternatives** - -| Capability | Teemops | AWS Security Hub | DIY Scripts | Enterprise CSPM | -|------------|---------|------------------|-------------|-----------------| -| Setup Time | 5 min | 30 min | Days/Weeks | Weeks | -| Pricing | From $0 | Pay-per-check | Free (your time) | $$$$ | -| Remediation Guidance | ✓ Detailed | Basic | None | Varies | -| Multi-Account | ✓ | Limited | Manual | ✓ | -| Compliance Reports | ✓ | Basic | None | ✓ | -| SMB Friendly | ✓ | Somewhat | No | No | - ---- - -## Integration Section - -### Headline -**Works With Your Stack** - -### Integrations - -- **Slack** — Alerts to your team channels -- **Email** — SMTP or native -- **Webhooks** — Custom integrations -- **API** — Build your own workflows - -### Coming Soon -- Jira integration -- PagerDuty -- Microsoft Teams -- Terraform provider - ---- - -## CTA Section - -### Headline -**See All Your AWS Security Gaps** - -### Subheadline -Start your first scan in under 5 minutes. Free tier available. - -### CTA Buttons -- **Primary:** Start Free Scan -- **Secondary:** Book a Demo diff --git a/design/marketing/web/pages/homepage.md b/design/marketing/web/pages/homepage.md deleted file mode 100644 index ce53efba..00000000 --- a/design/marketing/web/pages/homepage.md +++ /dev/null @@ -1,202 +0,0 @@ -# Homepage Content - -## Meta Information - -``` -Title: Teemops - AWS Security Scanning Made Simple -Description: Find AWS misconfigurations before attackers do. Continuous security scanning with CIS, PCI-DSS, SOC 2 compliance monitoring. Start free. -Keywords: AWS security scanning, cloud security, AWS misconfiguration, CIS benchmarks, compliance monitoring -``` - ---- - -## Hero Section - -### Headline -**AWS Security Scanning Made Simple** - -### Subheadline -Find misconfigurations before attackers do. Get actionable fixes in minutes, not weeks. - -### CTA Buttons -- **Primary:** Start Free Scan -- **Secondary:** See How It Works - -### Hero Visual -Dashboard screenshot showing security findings overview - ---- - -## Problem Section - -### Headline -**Your AWS Account Is Probably Exposed Right Now** - -### Body Copy -Most cloud breaches aren't sophisticated attacks. They're simple misconfigurations: - -- Public S3 buckets leaking customer data -- IAM policies with wildcard permissions -- Security groups open to the internet -- Unencrypted databases accessible from anywhere - -**You're one misconfiguration away from a headline you don't want.** - -The average data breach costs $4.45 million. For SMBs, it can mean the end of your business. - ---- - -## Solution Section - -### Headline -**Know Exactly What's Wrong—And How to Fix It** - -### Body Copy -Teemops continuously scans your AWS accounts and tells you: - -1. **What's misconfigured** — in plain English, not AWS jargon -2. **How severe it is** — prioritized by actual risk, not noise -3. **How to fix it** — step-by-step remediation for every finding - -No security team required. No 80-page audit reports. Just clarity. - ---- - -## Features Overview - -### Headline -**Everything You Need to Secure AWS** - -### Feature Cards - -**1. Continuous Security Scanning** -Automatic daily scans across all your AWS accounts. S3, IAM, EC2, RDS, and more. - -**2. Compliance Monitoring** -Stay compliant with CIS AWS Benchmarks, PCI-DSS, and SOC 2. Know your compliance score in real-time. - -**3. Multi-Account Dashboard** -See security posture across all AWS accounts in one view. Perfect for agencies and multi-product companies. - -**4. Actionable Remediation** -Every finding includes step-by-step fix instructions. Copy-paste CLI commands or CloudFormation templates. - -**5. Risk Prioritization** -Focus on what matters. Findings sorted by severity and exploitability, not just compliance checkboxes. - -**6. Instant Alerts** -Get notified when critical issues are found. Slack, email, or webhook integrations. - ---- - -## How It Works Section - -### Headline -**Secure Your AWS in 3 Steps** - -### Steps - -**Step 1: Connect Your AWS Account** -One-click CloudFormation setup. Read-only access—we never modify your resources. -*Time: 2 minutes* - -**Step 2: Run Your First Scan** -We scan your entire AWS environment against 100+ security checks. -*Time: 5 minutes* - -**Step 3: Fix What Matters** -See prioritized findings with clear remediation steps. Fix issues with confidence. -*Time: You decide* - -### CTA -**Start Your Free Scan →** - ---- - -## Social Proof Section - -### Headline -**Trusted by Growing Tech Companies** - -### Stats -- **1,000+** AWS accounts scanned -- **50,000+** misconfigurations found -- **100+** security checks -- **< 5 min** average time to first scan - -### Testimonials (Placeholder) - -> "We knew we had security gaps but didn't know where to start. Teemops showed us exactly what to fix first. Saved us from hiring a consultant." -> — **CTO, NZ SaaS Company (50 employees)** - -> "The compliance reporting alone is worth it. Our auditors love the CIS benchmark reports." -> — **VP Engineering, Fintech Startup** - -### Logo Bar -[Customer logos will go here] - ---- - -## Pricing Teaser Section - -### Headline -**Start Free. Scale When Ready.** - -### Copy -Free for 1 AWS account. Paid plans from **$99/month**. - -No credit card required. Cancel anytime. - -### CTA -**See Pricing →** - ---- - -## Final CTA Section - -### Headline -**Stop Guessing. Start Knowing.** - -### Subheadline -See your AWS security posture in the next 5 minutes. - -### CTA Buttons -- **Primary:** Start Free Scan -- **Secondary:** Book a Demo - ---- - -## Footer - -### Links -- Features -- Pricing -- Security -- Documentation -- Blog -- About -- Contact -- Privacy Policy -- Terms of Service - -### Social -- LinkedIn -- Twitter/X -- GitHub - -### Copyright -© 2026 Teemops. All rights reserved. - ---- - -## SEO Notes - -### Internal Links -- Link "CIS AWS Benchmarks" to /compliance/cis-benchmarks -- Link "PCI-DSS" to /compliance/pci-dss -- Link "S3 buckets" to /features (S3 scanning section) - -### Schema Markup -- Organization schema -- Product schema -- FAQ schema (if FAQ added) diff --git a/design/marketing/web/pages/pricing.md b/design/marketing/web/pages/pricing.md deleted file mode 100644 index cb3b1635..00000000 --- a/design/marketing/web/pages/pricing.md +++ /dev/null @@ -1,230 +0,0 @@ -# Pricing Page Content - -## Meta Information - -``` -Title: Pricing - Teemops AWS Security Scanning -Description: Simple, transparent pricing for AWS security scanning. Free tier available. Plans from $99/month. No credit card required to start. -Keywords: AWS security pricing, cloud security cost, CSPM pricing -``` - ---- - -## Hero Section - -### Headline -**Simple Pricing. No Surprises.** - -### Subheadline -Start free. Upgrade when you're ready. Cancel anytime. - ---- - -## Pricing Tiers - -### Free -**$0/month** -*Perfect for getting started* - -**Includes:** -- 1 AWS account -- Weekly scans -- Basic security checks (25+) -- Email alerts -- 7-day finding history -- Community support - -**CTA:** Get Started Free - ---- - -### Starter -**$99/month** (or $79/month billed annually) -*For small teams and startups* - -**Includes:** -- Up to 3 AWS accounts -- Daily scans -- Full security checks (100+) -- CIS Benchmark reports -- Email + Slack alerts -- 30-day finding history -- Email support - -**CTA:** Start 14-Day Trial - ---- - -### Pro -**$299/month** (or $249/month billed annually) -*For growing companies* - -**Everything in Starter, plus:** -- Up to 10 AWS accounts -- Hourly scan scheduling -- PCI-DSS compliance reports -- SOC 2 compliance reports -- Custom scan configurations -- API access -- 90-day finding history -- Priority email support - -**CTA:** Start 14-Day Trial - -**Most Popular** badge - ---- - -### Business -**Custom pricing** -*For larger organizations* - -**Everything in Pro, plus:** -- Unlimited AWS accounts -- Real-time continuous scanning -- Custom compliance frameworks -- SSO/SAML integration -- Dedicated account manager -- Unlimited history retention -- SLA guarantee -- Phone support - -**CTA:** Contact Sales - ---- - -## Feature Comparison Table - -| Feature | Free | Starter | Pro | Business | -|---------|------|---------|-----|----------| -| **AWS Accounts** | 1 | 3 | 10 | Unlimited | -| **Scan Frequency** | Weekly | Daily | Hourly | Real-time | -| **Security Checks** | 25+ | 100+ | 100+ | 100+ | -| **S3 Scanning** | ✓ | ✓ | ✓ | ✓ | -| **IAM Scanning** | ✓ | ✓ | ✓ | ✓ | -| **EC2/VPC Scanning** | ✓ | ✓ | ✓ | ✓ | -| **RDS Scanning** | ✓ | ✓ | ✓ | ✓ | -| **CloudTrail Scanning** | — | ✓ | ✓ | ✓ | -| **Lambda Scanning** | — | ✓ | ✓ | ✓ | -| **CIS Benchmarks** | Basic | Full | Full | Full | -| **PCI-DSS Reports** | — | — | ✓ | ✓ | -| **SOC 2 Reports** | — | — | ✓ | ✓ | -| **Custom Frameworks** | — | — | — | ✓ | -| **Email Alerts** | ✓ | ✓ | ✓ | ✓ | -| **Slack Integration** | — | ✓ | ✓ | ✓ | -| **Webhook Integration** | — | — | ✓ | ✓ | -| **API Access** | — | — | ✓ | ✓ | -| **Finding History** | 7 days | 30 days | 90 days | Unlimited | -| **PDF/CSV Export** | — | ✓ | ✓ | ✓ | -| **Team Members** | 1 | 5 | 15 | Unlimited | -| **SSO/SAML** | — | — | — | ✓ | -| **Support** | Community | Email | Priority | Dedicated | -| **SLA** | — | — | — | ✓ | - ---- - -## FAQ Section - -### General - -**Do I need a credit card to start?** -No. The free tier requires no credit card. We only ask for payment when you upgrade to a paid plan. - -**Can I change plans anytime?** -Yes. Upgrade, downgrade, or cancel at any time. Changes take effect immediately, and we prorate any differences. - -**What payment methods do you accept?** -We accept all major credit cards (Visa, Mastercard, Amex) and can arrange invoicing for annual Business plans. - -**Do you offer discounts for annual billing?** -Yes. Save ~20% when you pay annually instead of monthly. - -**Is there a discount for startups or non-profits?** -Yes. We offer 50% off for early-stage startups (under $1M funding) and registered non-profits. Contact us to apply. - ---- - -### Technical - -**What AWS permissions do you need?** -We use a read-only IAM role. We never modify, delete, or create resources in your AWS account. See our [Security page](/security) for details. - -**How long does setup take?** -About 2 minutes. We provide a one-click CloudFormation template that creates the required IAM role automatically. - -**Can I scan multiple AWS accounts?** -Yes. All paid plans support multiple AWS accounts. The free tier is limited to 1 account. - -**What regions do you support?** -We scan all AWS regions by default. You can customize which regions to include in your scans. - -**Do you support AWS Organizations?** -Not yet, but it's on our roadmap. Currently, you add each AWS account individually. - ---- - -### Security & Compliance - -**Is my data secure?** -Yes. We encrypt all data in transit and at rest. We never store your AWS credentials—we use IAM roles with temporary credentials. See our [Security page](/security). - -**Can I use Teemops for compliance audits?** -Yes. Our CIS, PCI-DSS, and SOC 2 reports are designed to support your compliance efforts. Many customers use our reports as evidence for auditors. - -**Do you have SOC 2 certification?** -We're currently pursuing SOC 2 Type II certification. Expected completion Q2 2026. - ---- - -### Billing - -**How do you count AWS accounts?** -Each unique AWS Account ID counts as one account. Adding the same account multiple times doesn't count extra. - -**What happens if I exceed my account limit?** -We'll notify you before your next billing cycle. You can either upgrade or remove accounts to stay within your limit. - -**Can I get a refund?** -We offer a 14-day money-back guarantee on all paid plans. No questions asked. - ---- - -## Enterprise CTA Section - -### Headline -**Need More?** - -### Body -For organizations with complex requirements, custom integrations, or regulatory needs—let's talk. - -- Unlimited AWS accounts -- Custom compliance frameworks -- Dedicated support -- Volume discounts -- Custom contracts - -### CTA -**Contact Sales →** - ---- - -## Final CTA Section - -### Headline -**Start Securing Your AWS Today** - -### Subheadline -No credit card required. Free tier available forever. - -### CTA -**Get Started Free →** - ---- - -## Trust Signals - -- "No credit card required" -- "14-day money-back guarantee" -- "Cancel anytime" -- "SOC 2 certification in progress" -- "Data encrypted at rest and in transit" diff --git a/design/marketing/web/pages/security.md b/design/marketing/web/pages/security.md deleted file mode 100644 index 25ba64e8..00000000 --- a/design/marketing/web/pages/security.md +++ /dev/null @@ -1,237 +0,0 @@ -# Security Page Content - -## Meta Information - -``` -Title: Security - How Teemops Protects Your Data -Description: Learn how Teemops secures your data. Read-only AWS access, encryption, and security practices for our cloud security platform. -``` - ---- - -## Hero Section - -### Headline -**Security Is Our Business** - -### Subheadline -We protect the data you trust us with. Here's how. - ---- - -## Our Security Commitment - -### Headline -**We Practice What We Scan** - -### Body -As a security company, we hold ourselves to the highest standards. We use the same security practices we recommend to our customers—and more. - ---- - -## AWS Access Model - -### Headline -**Read-Only Access. Always.** - -### How It Works - -**IAM Role-Based Access** -We never ask for AWS access keys. Instead, you deploy a CloudFormation template that creates a read-only IAM role in your account. - -**Least Privilege Principle** -Our IAM role has only the permissions needed to read resource configurations. We cannot create, modify, or delete any resources in your AWS account. - -**Temporary Credentials** -We use AWS STS to assume the role with temporary credentials that expire automatically. No long-lived credentials. - -**External ID Protection** -Each AWS account connection uses a unique External ID, preventing confused deputy attacks. - -### What We Can Access - -| Access Type | Permitted | Example | -|-------------|-----------|---------| -| Read configurations | ✓ | List S3 bucket policies | -| Read metadata | ✓ | Describe EC2 instances | -| Read data content | ✗ | Cannot read objects in S3 | -| Modify resources | ✗ | Cannot change configurations | -| Create resources | ✗ | Cannot create new resources | -| Delete resources | ✗ | Cannot delete anything | - -### IAM Policy - -Our IAM role uses these AWS managed policies: -- `SecurityAudit` — Standard AWS security audit permissions -- `ViewOnlyAccess` — Read-only access to configurations - -Full IAM policy available in our [CloudFormation template](link). - ---- - -## Data Protection - -### Headline -**Your Data, Protected** - -### Encryption - -**In Transit** -All data transmitted between your browser, our servers, and AWS uses TLS 1.3 encryption. - -**At Rest** -All data stored in our databases is encrypted using AES-256 encryption. - -**Secrets** -AWS role ARNs and sensitive configuration data are encrypted with additional application-level encryption. - -### Data Handling - -**What We Store:** -- AWS resource configurations (metadata only) -- Security findings and scan results -- Account settings and preferences - -**What We Never Store:** -- AWS access keys or secrets -- Actual data from your S3 buckets, databases, etc. -- Customer/user PII from your applications - -### Data Retention - -| Data Type | Retention | Notes | -|-----------|-----------|-------| -| Scan results | Per your plan | 7 days (Free) to unlimited (Business) | -| Account data | While active | Deleted on account closure | -| Audit logs | 1 year | For security investigations | - -### Data Location - -All data is stored in AWS data centers in [Sydney, Australia / or your region]. We do not transfer data outside this region without explicit consent. - ---- - -## Infrastructure Security - -### Headline -**Our Infrastructure, Secured** - -### Cloud Infrastructure - -We run on AWS and apply the same security standards we recommend: - -- **VPC isolation** — All services in private subnets -- **Security groups** — Strict firewall rules -- **Encryption** — All storage encrypted -- **Monitoring** — CloudTrail, CloudWatch, GuardDuty enabled -- **Updates** — Regular patching and updates - -### Application Security - -- **Authentication** — Firebase Authentication with MFA support -- **Authorization** — Role-based access control -- **Input validation** — All inputs sanitized -- **HTTPS only** — HSTS enforced -- **Dependencies** — Automated vulnerability scanning - ---- - -## Compliance - -### Headline -**Our Compliance Status** - -### Current - -| Standard | Status | -|----------|--------| -| SOC 2 Type II | In progress (expected Q2 2026) | -| ISO 27001 | Planned | -| GDPR | Compliant | -| Privacy Act 2020 (NZ) | Compliant | - -### Security Practices - -We follow industry-standard security practices: - -- Regular penetration testing -- Vulnerability scanning -- Security code reviews -- Employee security training -- Incident response procedures -- Business continuity planning - ---- - -## Responsible Disclosure - -### Headline -**Found a Vulnerability?** - -### Body -We appreciate security researchers who help us keep Teemops secure. - -### How to Report - -Email: **security@teemops.com** - -Please include: -- Description of the vulnerability -- Steps to reproduce -- Potential impact -- Your contact information - -### Our Commitment - -- Acknowledge receipt within 24 hours -- Investigate and provide updates -- Fix confirmed vulnerabilities promptly -- Credit reporters (if desired) -- No legal action against good-faith researchers - -### Scope - -**In scope:** -- teemops.com -- app.teemops.com -- API endpoints - -**Out of scope:** -- Physical attacks -- Social engineering -- Denial of service -- Third-party services - ---- - -## Security FAQ - -**Can Teemops access my data in S3?** -No. We can only see bucket configurations (policies, encryption settings). We cannot read, download, or access the objects/files stored in your buckets. - -**Can Teemops make changes to my AWS account?** -No. Our IAM role is strictly read-only. We cannot create, modify, or delete any resources. - -**What happens if Teemops is breached?** -Attackers would not gain access to your AWS accounts. We don't store credentials—only temporary role ARNs. You can revoke the IAM role at any time to immediately remove our access. - -**Can I revoke access?** -Yes, instantly. Simply delete the CloudFormation stack in your AWS account, and our access is immediately revoked. - -**Do you share data with third parties?** -No. We never sell or share your data. We only use trusted sub-processors for infrastructure (AWS) and analytics. - -**How do you handle incidents?** -We have a documented incident response plan. In the event of a security incident affecting your data, we will notify you within 72 hours as required by applicable regulations. - ---- - -## Contact Security Team - -### Questions? - -For security-related questions or concerns: - -**Email:** security@teemops.com - -For non-security inquiries, please use our [Contact page](/contact). diff --git a/design/marketing/web/pages/use-cases.md b/design/marketing/web/pages/use-cases.md deleted file mode 100644 index b6ab2b1f..00000000 --- a/design/marketing/web/pages/use-cases.md +++ /dev/null @@ -1,326 +0,0 @@ -# Use Case Pages Content - ---- - -## Use Case: SaaS Companies (/use-cases/saas-companies) - -### Meta Information -``` -Title: AWS Security for SaaS Companies | Teemops -Description: Cloud security scanning built for SaaS companies. Protect customer data, achieve SOC 2 compliance, and scale securely on AWS. -``` - -### Hero Section - -**Headline:** AWS Security for Fast-Moving SaaS Teams - -**Subheadline:** Ship features, not vulnerabilities. Continuous security scanning that keeps pace with your development velocity. - -**CTA:** Start Free Scan - ---- - -### The SaaS Security Challenge - -**Headline:** You're Moving Fast. Your Security Can't Keep Up. - -**Body:** -Your team ships multiple times a day. New features, new infrastructure, new attack surface. - -Meanwhile: -- **Your customers expect security.** Enterprise buyers require SOC 2 compliance. -- **You don't have a security team.** Your CTO wears the security hat (among many others). -- **Breaches kill SaaS companies.** Customer trust is everything. - -The last thing you need is a security blind spot waiting to become tomorrow's incident. - ---- - -### How Teemops Helps SaaS Companies - -**1. Continuous Visibility** -Know your security posture every day—not just before fundraising due diligence. - -**2. SOC 2 Compliance** -Map findings to SOC 2 controls. Show auditors you're serious about security. - -**3. Developer-Friendly** -Remediation guidance that engineers understand. CLI commands, CloudFormation, actual fixes. - -**4. Scale with You** -One account or fifty. Production, staging, dev environments—all visible in one dashboard. - ---- - -### Common SaaS Security Findings - -| Finding | Risk | How Often We See It | -|---------|------|---------------------| -| S3 bucket publicly accessible | Customer data exposure | 40% of accounts | -| IAM roles with wildcard permissions | Privilege escalation | 60% of accounts | -| RDS instances publicly accessible | Database breach | 25% of accounts | -| No MFA on root account | Account takeover | 35% of accounts | -| Security groups allow 0.0.0.0/0 | Unauthorized access | 55% of accounts | - ---- - -### Testimonial (Placeholder) - -> "We were 3 weeks from our SOC 2 audit and had no idea what our security posture looked like. Teemops showed us exactly what to fix. We passed." -> — **CTO, B2B SaaS Company (75 employees)** - ---- - -### CTA Section - -**Headline:** Secure Your SaaS—Today - -**Body:** Most SaaS companies have security gaps they don't know about. Find yours in 5 minutes. - -**CTA:** Start Free Scan - ---- ---- - -## Use Case: Fintech & Payments (/use-cases/fintech) - -### Meta Information -``` -Title: AWS Security for Fintech & Payments | Teemops -Description: PCI-DSS compliant AWS security scanning for fintech companies. Protect financial data and meet compliance requirements. -``` - -### Hero Section - -**Headline:** AWS Security for Financial Services - -**Subheadline:** Handle money? Handle security. PCI-DSS compliance monitoring and continuous security scanning for fintech. - -**CTA:** Start Free Scan - ---- - -### The Fintech Security Reality - -**Headline:** Regulators, Auditors, and Hackers Are All Watching - -**Body:** -Financial services face unique security pressures: - -- **PCI-DSS compliance** is mandatory if you touch payment data -- **Regulators expect proof** of your security controls -- **You're a high-value target** for attackers (because money) -- **Customer trust is fragile** — one breach and they're gone - -You can't afford security guesswork. - ---- - -### How Teemops Helps Fintech - -**1. PCI-DSS Mapping** -Every finding mapped to PCI-DSS requirements. Know exactly what's compliant and what's not. - -**2. Audit-Ready Reports** -Generate compliance reports that satisfy auditors. No more scrambling before assessments. - -**3. Encryption Verification** -Verify encryption at rest and in transit across all services handling financial data. - -**4. Access Control Review** -Identify overly permissive IAM policies before they become audit findings. - ---- - -### Compliance Coverage - -| Requirement | Coverage | -|-------------|----------| -| PCI-DSS v4.0 | Full | -| SOC 2 Type II | Full | -| CIS AWS Benchmarks | Full | -| NZ Privacy Act | Supported | - ---- - -### Common Fintech Findings - -| Finding | PCI Requirement | Severity | -|---------|-----------------|----------| -| Unencrypted RDS database | Req. 3.4 | Critical | -| S3 without encryption | Req. 3.4 | High | -| Security group allows all inbound | Req. 1.3 | Critical | -| No CloudTrail logging | Req. 10.2 | High | -| Root account without MFA | Req. 8.3 | Critical | - ---- - -### CTA Section - -**Headline:** Compliance Confidence for Fintech - -**Body:** Know your PCI-DSS compliance status right now. Not in 3 weeks when the auditor asks. - -**CTA:** Start Free Scan - ---- ---- - -## Use Case: Healthtech (/use-cases/healthtech) - -### Meta Information -``` -Title: AWS Security for Healthtech | Teemops -Description: Protect patient data on AWS. Security scanning and compliance monitoring for healthtech and digital health companies. -``` - -### Hero Section - -**Headline:** AWS Security for Digital Health - -**Subheadline:** Patient data is sacred. Protect it with continuous security monitoring. - -**CTA:** Start Free Scan - ---- - -### The Healthtech Security Challenge - -**Headline:** Health Data Requires Healthcare-Grade Security - -**Body:** -Digital health companies handle the most sensitive data imaginable: - -- **Patient records** protected by strict privacy laws -- **Health Insurance Portability** requirements (where applicable) -- **Privacy Act 2020 (NZ)** mandatory breach notification -- **Customer trust** built on data protection promises - -A breach doesn't just cost money—it harms patients and destroys trust. - ---- - -### How Teemops Helps Healthtech - -**1. Data Protection Verification** -Ensure all storage (S3, RDS, EBS) is encrypted and access-controlled. - -**2. Access Logging** -Verify audit trails exist for all access to sensitive data. - -**3. Network Isolation** -Check that databases and health data aren't publicly accessible. - -**4. Compliance Reporting** -Reports aligned with health data protection requirements. - ---- - -### Common Healthtech Findings - -| Finding | Why It Matters | Severity | -|---------|----------------|----------| -| RDS publicly accessible | Patient data exposed | Critical | -| S3 bucket without encryption | Health records unprotected | Critical | -| No VPC flow logs | Can't detect unauthorized access | High | -| IAM policies too permissive | Insider threat risk | High | -| CloudTrail not enabled | No audit trail | High | - ---- - -### CTA Section - -**Headline:** Protect Patient Trust - -**Body:** Your patients trust you with their health data. Make sure AWS isn't the weak link. - -**CTA:** Start Free Scan - ---- ---- - -## Use Case: Digital Agencies (/use-cases/agencies) - -### Meta Information -``` -Title: AWS Security for Digital Agencies | Teemops -Description: Manage security across multiple client AWS accounts. Multi-tenant dashboard for agencies managing client infrastructure. -``` - -### Hero Section - -**Headline:** AWS Security for Digital Agencies - -**Subheadline:** Managing client AWS accounts? See security across all of them—without the chaos. - -**CTA:** Start Free Scan - ---- - -### The Agency Security Challenge - -**Headline:** Multiple Clients. Multiple AWS Accounts. Multiple Headaches. - -**Body:** -Agencies face unique security challenges: - -- **Varying client security maturity** — some care, some don't (until breach) -- **Liability exposure** — if their AWS gets breached, who's responsible? -- **No central visibility** — each client is a separate silo -- **Limited time** — security can't eat into delivery time - -You need security visibility without the overhead. - ---- - -### How Teemops Helps Agencies - -**1. Multi-Tenant Dashboard** -Separate organizations for each client. One login for all. - -**2. Client-Ready Reports** -Generate branded reports showing client security posture. - -**3. Quick Onboarding** -Add new client AWS accounts in minutes. - -**4. Liability Protection** -Document security recommendations. CYA when things go wrong. - ---- - -### Agency Workflow - -**New Client Onboarding:** -1. Add client as new organization -2. Connect their AWS account (2 min) -3. Run initial scan -4. Send them findings report -5. Fix or recommend fixes - -**Ongoing Management:** -- Weekly automated scans -- Monthly security reports -- Alert on critical findings - ---- - -### Pricing for Agencies - -| Plan | AWS Accounts | Best For | -|------|--------------|----------| -| Starter | 3 | 1-2 clients | -| Pro | 10 | 3-8 clients | -| Business | Unlimited | 10+ clients | - -Volume discounts available for agency partners. - ---- - -### CTA Section - -**Headline:** Elevate Your Client Security Offering - -**Body:** Add security scanning to your services. Protect clients, reduce liability, add revenue. - -**CTA:** Start Free Scan diff --git a/design/marketing/web/pricing-strategy.md b/design/marketing/web/pricing-strategy.md deleted file mode 100644 index ae2e0bbc..00000000 --- a/design/marketing/web/pricing-strategy.md +++ /dev/null @@ -1,431 +0,0 @@ -# Teemops Pricing Strategy - -## Executive Summary - -This document outlines the pricing strategy for Teemops' go-to-market launch, targeting SMBs (20-200 employees) in SaaS, Fintech, and Healthtech industries, with initial focus on the NZ market. - ---- - -## Pricing Philosophy - -### Core Principles - -1. **Value-Based Pricing** — Price based on value delivered (security + compliance + time saved), not cost to serve -2. **Land and Expand** — Start customers on lower tiers, grow with their needs -3. **Transparent & Simple** — No hidden fees, clear feature boundaries -4. **Freemium for Acquisition** — Free tier to reduce friction and build trust - -### Positioning - -| Position | Description | -|----------|-------------| -| **Not the cheapest** | We're not competing on price with DIY/open source | -| **Not enterprise pricing** | Accessible to SMBs without procurement hoops | -| **Best value for SMBs** | Sweet spot between free tools and enterprise CSPM | - ---- - -## Pricing Structure - -### Recommended Tiers - -| Tier | Price (NZD) | Price (USD) | Target Customer | -|------|-------------|-------------|-----------------| -| **Free** | $0 | $0 | Individual devs, evaluation | -| **Starter** | $149/mo | $99/mo | Small startups (10-30 staff) | -| **Pro** | $449/mo | $299/mo | Scale-ups (30-100 staff) | -| **Business** | Custom | Custom | Mid-market (100-500 staff) | - -### Annual Discount -- **20% off** for annual commitment -- Starter: $119/mo billed annually ($1,428/yr) -- Pro: $359/mo billed annually ($4,308/yr) - ---- - -## Tier Details - -### Free Tier - -**Purpose:** Acquisition, evaluation, word-of-mouth - -| Feature | Limit | -|---------|-------| -| AWS Accounts | 1 | -| Scan Frequency | Weekly | -| Security Checks | 25 (basic) | -| History | 7 days | -| Users | 1 | -| Support | Community/docs | - -**Conversion Goal:** 10-15% convert to paid within 60 days - -**Why Free Works:** -- Reduces signup friction (no credit card) -- Lets users experience value before paying -- Creates word-of-mouth in developer communities -- Captures leads for nurturing - ---- - -### Starter Tier ($149 NZD / $99 USD) - -**Purpose:** First paid tier, small teams - -| Feature | Limit | -|---------|-------| -| AWS Accounts | 3 | -| Scan Frequency | Daily | -| Security Checks | 100+ (full) | -| Compliance | CIS Benchmarks | -| History | 30 days | -| Users | 5 | -| Integrations | Email, Slack | -| Support | Email (48hr response) | - -**Target Customer:** -- Early-stage startups -- Small dev teams -- Side projects with production AWS - -**Value Justification:** -- 1 hour of security consultant = $200-400 NZD -- Starter saves 5+ hours/month = $1,000+ value -- Price is <15% of value delivered - ---- - -### Pro Tier ($449 NZD / $299 USD) - -**Purpose:** Core revenue driver, growing companies - -| Feature | Limit | -|---------|-------| -| AWS Accounts | 10 | -| Scan Frequency | Hourly | -| Security Checks | 100+ (full) | -| Compliance | CIS, PCI-DSS, SOC 2 | -| History | 90 days | -| Users | 15 | -| Integrations | Email, Slack, Webhooks, API | -| Support | Priority email (24hr response) | -| Extras | Custom scan configs | - -**Target Customer:** -- Scale-ups with compliance needs -- Fintech/Healthtech with audits -- Companies with multiple environments - -**Value Justification:** -- SOC 2 audit prep consulting = $10,000-50,000 NZD -- PCI compliance assessment = $5,000-20,000 NZD -- Pro tier = $5,388/year = <10% of compliance costs - ---- - -### Business Tier (Custom) - -**Purpose:** Larger organizations, higher ACV - -| Feature | Limit | -|---------|-------| -| AWS Accounts | Unlimited | -| Scan Frequency | Real-time/continuous | -| Security Checks | 100+ (full) | -| Compliance | All + Custom frameworks | -| History | Unlimited | -| Users | Unlimited | -| Integrations | All + SSO/SAML | -| Support | Dedicated CSM, phone | -| Extras | Custom SLAs, on-call | - -**Target Customer:** -- Companies with 10+ AWS accounts -- Agencies managing client accounts -- Organizations requiring SSO - -**Pricing Approach:** -- Base: $999 NZD/month ($12,000/year) -- Per additional AWS account: $50-100/month -- Or negotiate based on total value - ---- - -## Pricing Psychology - -### Anchoring - -- Show Business tier first (anchors high) -- Pro becomes "reasonable" by comparison -- Starter feels like a "deal" - -### Decoy Effect - -- Pro is the target tier -- Starter exists to make Pro look valuable -- Feature gap between Starter→Pro is significant - -### Price Endings - -- Use $X49 or $X99 (not round numbers) -- $149 feels cheaper than $150 -- $449 feels cheaper than $450 - -### Social Proof on Pricing - -- "Most Popular" badge on Pro tier -- Customer count or logos near pricing -- "Join 500+ companies" type messaging - ---- - -## Launch Pricing Strategy - -### Phase 1: Beta/Early Access (Month 1-2) - -**Goal:** Get first 10-20 paying customers, gather feedback - -| Offer | Details | -|-------|---------| -| **Founding Member Discount** | 50% off first year | -| **Extended Trial** | 30 days instead of 14 | -| **Locked-in Price** | Price guaranteed for 2 years | - -**Messaging:** -> "Join as a founding member. Get 50% off your first year and lock in this price forever." - -**Why This Works:** -- Creates urgency (limited spots) -- Rewards early adopters -- Builds case studies and testimonials - ---- - -### Phase 2: Public Launch (Month 3-4) - -**Goal:** Scale acquisition, establish market pricing - -| Offer | Details | -|-------|---------| -| **Launch Discount** | 20% off first 3 months | -| **Annual Incentive** | Extra month free on annual | -| **Referral Program** | $50 credit per referral | - -**Remove:** -- Founding member pricing (scarcity) -- Extended trials (back to 14 days) - ---- - -### Phase 3: Growth (Month 5+) - -**Goal:** Optimize pricing, increase ACV - -| Action | Details | -|--------|---------| -| **Price Testing** | A/B test pricing page | -| **Tier Adjustments** | Based on usage data | -| **Add-ons** | Premium support, extra accounts | -| **Usage Pricing** | Consider per-account pricing | - ---- - -## NZ Market Considerations - -### Currency - -| Approach | Pros | Cons | -|----------|------|------| -| **NZD only** | Simple, local feel | Limits international | -| **USD only** | Standard for SaaS | Feels foreign to NZ | -| **Both (recommended)** | Best of both | More complexity | - -**Recommendation:** Show NZD by default for NZ visitors, USD for others. Use geo-detection. - -### NZ Pricing Sensitivity - -| Factor | Implication | -|--------|-------------| -| Smaller budgets | Price 20-30% below US competitors | -| Annual preference | Offer meaningful annual discount | -| Relationship-driven | Offer personal demos, not just self-serve | -| GST consideration | Prices should be +GST for NZ | - -### NZ-Specific Offers - -- **NZ Tech Startup Discount:** 50% off for NZ startups <$1M revenue -- **Kiwi Landing Pad Alumni:** Special pricing for KLP companies -- **NZTech Member Discount:** 10% off for NZTech members - ---- - -## Competitive Positioning - -### Price Comparison - -| Competitor | Pricing | Our Position | -|------------|---------|--------------| -| **AWS Security Hub** | ~$0.001/check | We're more actionable | -| **Prowler (OSS)** | Free | We save time, provide remediation | -| **Wiz** | $50k+/year | We're 10x cheaper, SMB-focused | -| **Orca** | $30k+/year | We're accessible to SMBs | -| **Lacework** | $50k+/year | Enterprise, not our market | -| **CloudSploit** | $100-500/mo | Similar, we're more modern | - -### Positioning Statement - -> "Enterprise-grade AWS security scanning at SMB-friendly prices. 10x cheaper than Wiz, 10x faster than doing it yourself." - ---- - -## Discounts & Promotions - -### Standard Discounts - -| Discount | Amount | Conditions | -|----------|--------|------------| -| Annual billing | 20% | Pay upfront | -| Startup program | 50% | <$1M revenue, <2 years old | -| Non-profit | 50% | Registered charity | -| Education | 50% | Educational institutions | - -### Promotional Discounts - -| Promotion | Use Case | Duration | -|-----------|----------|----------| -| Launch discount | Public launch | 3 months | -| Event discount | Conference/meetup | 1 month | -| Partner discount | Agency partners | Ongoing | -| Referral credit | Word of mouth | Ongoing | - -### Discount Rules - -1. **Max one discount** — Discounts don't stack -2. **First year only** — Startup/nonprofit discounts apply to year 1 -3. **Verify eligibility** — Require proof for startup/nonprofit -4. **No public coupons** — Avoid discount culture - ---- - -## Monetization Roadmap - -### Current (MVP) - -| Revenue Stream | Description | -|----------------|-------------| -| Subscription tiers | Free/Starter/Pro/Business | -| Annual upsell | 20% discount incentive | - -### Near-term (6-12 months) - -| Revenue Stream | Description | -|----------------|-------------| -| Additional AWS accounts | $50-100/account/month | -| Premium support | $200/month add-on | -| Compliance add-ons | $100/month per framework | - -### Long-term (12+ months) - -| Revenue Stream | Description | -|----------------|-------------| -| Multi-cloud (Azure, GCP) | Separate pricing tier | -| Professional services | Implementation, training | -| API access tiers | Usage-based API pricing | -| White-label/reseller | For MSPs and agencies | - ---- - -## Key Metrics to Track - -### Pricing Metrics - -| Metric | Target | Why It Matters | -|--------|--------|----------------| -| **Free→Paid Conversion** | 10-15% | Funnel health | -| **Trial→Paid Conversion** | 25-40% | Value demonstration | -| **Monthly Churn** | <5% | Pricing/value alignment | -| **Average Revenue Per User (ARPU)** | $200+ NZD | Revenue efficiency | -| **Annual Contract Value (ACV)** | $2,500+ NZD | Revenue predictability | -| **Expansion Revenue** | 20%+ of new ARR | Land and expand working | - -### Pricing Page Metrics - -| Metric | Target | -|--------|--------| -| Pricing page visits | Track volume | -| Time on pricing page | 30-60 seconds | -| CTA click rate | 10-20% | -| Plan selection distribution | Pro = 50%+ | - ---- - -## Pricing Communication - -### How to Talk About Pricing - -**Do:** -- Lead with value, not price -- Compare to alternatives (time saved, consultant costs) -- Offer to discuss needs before quoting -- Be transparent about what's included - -**Don't:** -- Apologize for pricing -- Offer discounts unprompted -- Compete on price alone -- Hide pricing (creates distrust) - -### Objection Handling - -| Objection | Response | -|-----------|----------| -| "Too expensive" | "What's your current spend on security tools/consultants?" | -| "Can I get a discount?" | "We offer annual billing at 20% off. What's your timeline?" | -| "Competitor is cheaper" | "What features are most important to you? Let's compare." | -| "Need to think about it" | "What information would help you decide?" | -| "Free tier is enough" | "As you grow, you'll need [specific Pro features]. We're here when ready." | - ---- - -## Implementation Checklist - -### Before Launch - -- [ ] Implement pricing tiers in billing system -- [ ] Set up Stripe/payment processor -- [ ] Create pricing page with tier comparison -- [ ] Build upgrade/downgrade flows -- [ ] Set up trial expiration emails -- [ ] Create discount code system -- [ ] Document pricing for sales team - -### At Launch - -- [ ] Announce founding member pricing -- [ ] Set up conversion tracking -- [ ] Monitor trial→paid funnel -- [ ] Collect pricing feedback - -### Post-Launch (Monthly) - -- [ ] Review conversion rates -- [ ] Analyze churn by tier -- [ ] Survey churned customers on pricing -- [ ] A/B test pricing page elements - ---- - -## Summary - -| Element | Recommendation | -|---------|----------------| -| **Tiers** | Free / Starter ($149) / Pro ($449) / Business (custom) | -| **Annual discount** | 20% off | -| **Launch offer** | 50% founding member discount | -| **Target tier** | Pro (60% of revenue) | -| **NZ pricing** | Show NZD, 20-30% below US market | -| **Key metric** | 10%+ free→paid conversion | - ---- - -*Last updated: January 2026* diff --git a/design/marketing/web/wireframes/README.md b/design/marketing/web/wireframes/README.md deleted file mode 100644 index aedeb2cb..00000000 --- a/design/marketing/web/wireframes/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# Marketing site wireframes — v2 - -Low-fidelity wireframes for the teemops.com marketing site, redrawn after -[milestone 2 "Findings & Scans v2"](https://github.com/teemops/tops/milestone/2) closed -and after the open-source / self-hosted pivot. - -These are **structure and message**, not visual design. Once they are signed off, the -HTML mockups in `../html/` and the copy in `../pages/` get updated to match — in that -order. Do not update the HTML first; it is the expensive artefact. - -**Two formats, same content.** The markdown files below are the source of truth. The -same wireframes are also in [html/](html/) as renderable pages — open -[html/index.html](html/index.html) in a browser, no server or build needed. Reviewer -notes are inline and there is a **Hide notes** toggle in the top bar to see the layout -clean. - -`html/` is *not* `../html/`. These are greyscale, boxy and deliberately ugly, so nobody -mistakes a wireframe for a design decision; `../html/` holds the Tailwind mockups that -get built *after* sign-off. Keep the two apart — the wireframes are never deployed. - -| Wireframe | Replaces | Status | -| --- | --- | --- | -| [homepage.md](homepage.md) | `../pages/homepage.md`, `../html/index.html` | For review | -| [features.md](features.md) | `../pages/features.md`, `../html/features.html` | For review | -| [pricing.md](pricing.md) | deletes `../pages/pricing.md`, `../html/pricing.html` | For review | - -[pricing.md](pricing.md) is not a page wireframe — it is the case for **deleting** the -pricing page and what to do with the URL. teemops.com sells nothing. - -Not redrawn yet, and deliberately: `security.md`, `about.md`, `use-cases.md`, -`compliance.md`. They are behind too, but they are behind on *positioning*, not on -*product truth* — nothing in milestone 2 makes them wrong. The homepage, the features -page and the pricing page are the three that currently describe a product we do not -ship. One of those three stops existing. - -They will each need one small pass later for the "free tier" wording — that phrase -appears across `../pages/` and it implies a paid tier above it. The word for what we -have is just *free*. - ---- - -## Why the site needs redrawing - -Three things happened that the site has not caught up with. - -**1. The security score is gone.** `a246323` removed it rather than recalibrating it -(issue #91 — it was pinned at 0 and could not improve). The homepage hero mockup is -built around a `78/100` score readout (`../html/index.html:104`), and the features page -has three more score tiles (`../html/features.html:285,303,321`). The single most -prominent visual on the site demos a feature that no longer exists. - -**2. There is no SaaS to sign up for.** Every CTA on the site is "Start Free Scan" with -"No credit card required. Free tier available forever." underneath. There is no hosted -signup. The product installs with one Docker command, is Apache-2.0, and the README -leads with "Self-hosted, Apache-2.0, no limits and no paid tier". The word "open" does -not appear anywhere on the marketing site. - -**3. Milestone 2 shipped the things worth selling.** A finding is now a durable record -whose ignore/resolve status survives a rescan; scans can target one service; findings -filter by service and by benchmark; Insights groups by both. That is the difference -between "a scanner that produces a report" and "a backlog you can actually work" — and -it is the strongest product story we have. None of it is on the site. - ---- - -## Traceability — milestone 2 → website - -| Issue | Shipped | Where it shows up on the site | -| --- | --- | --- | -| #81 D-1 · Durable findings | one record per resource + rule | Homepage §4 "It remembers", features §2 — the headline capability | -| #90 B-1 · Status survives rescan | ignore/resolve persists | Same section; this is the proof point for #81 | -| #91 B-2 · Security score removed | — | Removes hero panel, removes 3 feature tiles. Nothing replaces the number | -| #84 F-2 · Per-service scans | scan one service, not a whole benchmark | Homepage §5, features §3 | -| #85 F-3 · Filter by service | URL-carried | Features §4 (grouped as "slice the backlog") | -| #87 F-4 · Filter by benchmark | benchmark recorded per finding | Features §4 + compliance page later | -| #83 F-7 · Filters in URL | shareable filtered views | Features §4, one line — it is a detail, not a section | -| #82 F-1 · Remediation in Findings | one-line fix on every finding | Homepage §4, features §5 | -| #86 S-1 · Scan detail summarises | summary + dispatch, not a second list | Product tour screenshot only | -| #88 F-5 · Insights by service | severity breakdown | Features §6 | -| #89 F-6 · Insights by benchmark | — | Features §6 | -| #92 · Multi-region parallel scans | + batch settlement `26630ac` | Features §3, one line. Speed claim — see open questions | - ---- - -## Positioning these wireframes assume - -Confirmed with the product owner, 2026-08-02: - -- **teemops.com stays completely free.** No tiers, no pricing page, no managed-hosting - offer, no support packages, no contact-sales form. The software is Apache-2.0 with no - feature gates and no seat limits, and the site says so plainly. -- **There is no SaaS version and we are not launching one yet.** Nothing on the site - should imply a hosted multi-tenant signup exists. -- **One commercial mention, site-wide**: a footer link to - [teem.cloud](https://teem.cloud) reading *"Teem is the company behind the open source - software. For AWS security auditing, view their website."* Specified in - [homepage.md](homepage.md) §10. -- **The Red Hat split.** Forever-free software here; a company behind it for customers - who need stability or help with setup and management — and everything about *that* - lives on teem.cloud, not here. - -So the site's job is simply **drive installs**. The primary conversion event is a copied -install command; the secondary is a GitHub star. There is no revenue event on this site, -by design — the moment teemops.com starts describing support offerings, every free claim -on it reads as a funnel. - -An earlier draft of this set had a three-card "who runs it" block on the homepage and a -full pricing page with managed and support tiers. Both are deleted. What survives of -that thinking is one footer sentence. - ---- - -## Open questions for the product owner - -These are flagged in the wireframes where they bite. None of them block drawing. - -1. **Does the "Free. Forever." band earn homepage space?** [pricing.md](pricing.md) - proposes a four-line band where `/pricing` redirects to. I recommend keeping it and - keeping it small; the counter-argument is that the hero and the Apache-2.0 badge - already say it and a whole band protests too much. Your call — it is the last - structural decision left in this set. -2. **Speed claim.** `7494959` instrumented scan phases to baseline "where the 10 minutes - goes", and multi-region now runs in parallel. The homepage wants a concrete number - ("first findings in N minutes"). I have left it as `[N]` — do not ship a number that - the instrumentation does not support. -3. **`../pricing-strategy.md` should move, not die.** 431 lines, now obsolete for this - site, but it holds the only written-down SMB segment analysis and it is plausible - input for teem.cloud. Move it out of `design/marketing/web/` rather than deleting it. -4. **`/contact` should probably go too.** It is still in the site structure in - `../content-plan.md`. A contact form on the project site is a sales channel wearing a - different hat; GitHub issues is the contact channel for a project, and teem.cloud can - own the rest. Not actioned in these wireframes — flagging it. -5. **Social proof.** There are no customers, logos or testimonials, and the current - homepage reserves a section for them. The wireframes replace that section with - repo signals (stars, checks, services, license) — honest, and available today. -6. **Screenshots.** Every wireframe calls for real UI screenshots and there are none in - `../` yet. Listed as the top asset gap; the app is running locally so these are cheap - to capture. diff --git a/design/marketing/web/wireframes/features.md b/design/marketing/web/wireframes/features.md deleted file mode 100644 index 75243889..00000000 --- a/design/marketing/web/wireframes/features.md +++ /dev/null @@ -1,256 +0,0 @@ -# Wireframe — Features (`/features`) - -**Job:** the evaluator has decided we are interesting and is now checking whether we do -the specific thing they need. This page is scanned, not read. Optimise for a reader -using ⌘F. - -**Primary CTA:** install command, repeated at top and bottom. -**Structure:** one section per capability, each answering "what does it do" in a -sentence, then showing it. - -The current page (`../pages/features.md`, 333 lines) is organised around a generic CSPM -feature list — scanning, compliance, multi-account, alerts, remediation, reporting, -integrations. Three of those sections describe things that either do not exist -(real-time alerts, integrations) or are now wrong (the three score tiles at -`../html/features.html:285,303,321`). This reorganises around what we actually ship. - ---- - -## Structure - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ 1. HERO + jump nav │ -│ 2. DURABLE FINDINGS ← #81, #90 │ -│ 3. SCANNING ← #84, #92, coverage table │ -│ 4. FILTER AND SLICE ← #85, #87, #83 │ -│ 5. REMEDIATION ← #82 │ -│ 6. INSIGHTS ← #88, #89 │ -│ 7. MULTI-TENANCY ← orgs, roles, isolation │ -│ 8. WHAT WE DON'T DO ← honest boundaries │ -│ 9. CTA │ -└──────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 1. Hero + jump nav - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Everything TOPS does │ -│ 74 checks across 11 AWS services. Self-hosted. Apache-2.0. │ -│ │ -│ Findings · Scanning · Filtering · Remediation · Insights · Teams │ -│ ────────────────────────────────────────────────────────────────── │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Sticky jump nav under the main nav on `lg+`. This page is long; anchor links are the -main navigation aid. Drop the jump nav below `md` rather than stacking two sticky bars. - ---- - -## 2. Durable findings - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Findings that persist │ -│ One record per resource and rule — not one row per scan. │ -│ │ -│ ┌────────────────────────────────────────────────────────────────┐ │ -│ │ ▌CRITICAL S3 bucket allows public read │ │ -│ │ arn:aws:s3:::acme-assets │ │ -│ │ First seen 12 Jun · Last seen 2 Aug · 51 days open│ │ -│ │ [ cis-2.1.5 ] [ S3 ] Status: ● Open │ │ -│ │ ────────────────────────────────────────────── │ │ -│ │ Fix: Enable Block Public Access on the bucket. │ │ -│ └────────────────────────────────────────────────────────────────┘ │ -│ │ -│ ✓ Mark resolved or ignored — it stays that way through the next scan│ -│ ✓ First-seen and last-seen on every finding │ -│ ✓ Reappears automatically if the misconfiguration comes back │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #81, #90, and the anatomy of a finding in one figure — every element on this card -is a separate capability, labelled once, and the sections below refer back to it. - -"51 days open" is the number that sells this. It is only computable because of #81. - ---- - -## 3. Scanning - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Scan what you need, when you need it │ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ Whole benchmark │ │ One service │ │ -│ │ CIS AWS Foundations, │ │ Changed one S3 policy│ │ -│ │ or the general basic │ │ ? Scan S3 and get an │ │ -│ │ profile │ │ answer in a fraction │ │ -│ │ │ │ of the time │ │ -│ └──────────────────────┘ └──────────────────────┘ │ -│ │ -│ Regions run in parallel. A ten-region account isn't ten times │ -│ the wait. │ -│ │ -│ ── Coverage ────────────────────────────────────────────────────── │ -│ S3 │ ██████ n checks │ IAM │ ██████ n checks │ -│ EC2 │ ████ n checks │ RDS │ ████ n checks │ -│ CloudTrail│ ███ n checks │ KMS │ ███ n checks │ -│ Lambda │ ██ n checks │ DynamoDB│ ██ n checks │ -│ ELBv2 │ ██ n checks │ SNS │ █ n checks │ -│ SQS │ █ n checks │ │ │ -│ [ See every check → docs ] │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #84 and #92. - -The coverage table is the highest-value block on the page for an evaluator — it is the -⌘F target. Per-service check counts must be **generated**, not typed; `scan:validate-rules` -walks the rule JSON and is the source. A stale count here is the kind of small -inaccuracy that loses a technical buyer. - -Link out to a full check listing in the docs rather than inlining 74 rows. - ---- - -## 4. Filter and slice - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Cut 400 findings down to the 8 you're working on │ -│ │ -│ ┌────────────────────────────────────────────────────────────────┐ │ -│ │ [ Account: prod ▾ ] [ Service: S3 ▾ ] [ Benchmark: CIS 2.x ▾ ] │ │ -│ │ [ Severity: Critical ▾ ] [ Status: Open ▾ ] 12 results │ │ -│ └────────────────────────────────────────────────────────────────┘ │ -│ │ -│ /findings?service=s3&benchmark=cis&status=open │ -│ ↑ every filter is in the URL — bookmark it, paste it in Slack, │ -│ send it to the person who owns S3 │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #85, #87, #83. The URL under the filter bar is the whole point of the section — -render it as visible monospace text, not a caption. - -Benchmark filtering only works because findings record which benchmark raised them -(`a74a6c3`). Worth one sentence: a finding knows which control it came from, so a -compliance question has a direct answer. - ---- - -## 5. Remediation - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Every finding tells you how to fix it │ -│ │ -│ ┌───────────────────────────┐ ┌───────────────────────────────┐ │ -│ │ In the list │ │ On the finding │ │ -│ │ │ │ │ │ -│ │ ▌HIGH RDS is public │ │ 1. Open the RDS console │ │ -│ │ Set PubliclyAccessible │ │ 2. Modify → Connectivity │ │ -│ │ to false ← 1 │ │ 3. Public access → No │ │ -│ │ line, no click needed │ │ 4. Apply immediately │ │ -│ │ │ │ [ AWS docs → ] │ │ -│ └───────────────────────────┘ └───────────────────────────────┘ │ -│ │ -│ Step-by-step guidance on every critical and high finding. │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #82. The left/right split makes the distinction the product actually draws: a -one-liner everywhere, full steps on critical and high. Do not imply full step-by-step -exists on all 74 checks — the README is precise about this and the site should match. - ---- - -## 6. Insights - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Where the problems actually are │ -│ │ -│ ┌─────────────────────────────┐ ┌─────────────────────────────┐ │ -│ │ By service │ │ By benchmark │ │ -│ │ with a severity breakdown │ │ which controls are failing │ │ -│ │ per service, so "42 in S3" │ │ and how badly │ │ -│ │ becomes "12 critical in S3"│ │ │ │ -│ └─────────────────────────────┘ └─────────────────────────────┘ │ -│ │ -│ Also: findings trend over a period, severity distribution, │ -│ remediation rate. │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #88, #89. The trend / distribution / remediation-rate line covers what Insights -already had, briefly — it is table stakes, not differentiation, and should not get -equal billing with the two groupings. - -**No score, no grade, no single health number anywhere on this page.** - ---- - -## 7. Teams and isolation - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Built multi-tenant from the schema up │ -│ │ -│ Organisations · team roles · every query scoped by organisation │ -│ Run one instance for several clients, or several teams, without │ -│ one seeing another's findings. │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Short. Relevant to agencies and MSPs — a real segment for a self-hosted scanner — and -it is genuinely enforced rather than aspirational, so we can state it flatly. - ---- - -## 8. What we don't do - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ What TOPS doesn't do (yet) │ -│ │ -│ ✗ Azure or GCP — AWS only │ -│ ✗ Auto-remediation — we tell you the fix, you apply it │ -│ ✗ Real-time alerting / webhooks — scans are on demand │ -│ ✗ Agent-based runtime monitoring — this is config scanning │ -│ │ -│ Roadmap → github.com/teemops/tops │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -**Recommend keeping this section.** It disqualifies bad-fit visitors before they install -and bounce, it is unusual enough to be memorable, and for an open-source project it -reads as confidence. It also lets us delete the current page's "Real-time Alerts" and -"Integrations (future)" sections honestly rather than leaving them as vapour. - -Verify each line against the roadmap before shipping — this section is only an asset -while it is accurate. - ---- - -## 9. CTA - -Same block as [homepage.md](homepage.md) §9. Install command, "read the script first", -GitHub star. No paid alternative offered here or anywhere else on the page — the only -commercial mention on the site is the footer line in [homepage.md](homepage.md) §10. - ---- - -## Deleted from the current features page - -- Three "Score" tiles (`../html/features.html:285,303,321`) — feature removed in `a246323` -- "Real-time Alerts" section — does not exist; now a line in §8 -- "Integrations (future)" section — does not exist; now a line in §8 -- "Reporting & Exports" as a headline section — demote to a line unless we can screenshot it -- All "Start Free Scan" CTAs diff --git a/design/marketing/web/wireframes/homepage.md b/design/marketing/web/wireframes/homepage.md deleted file mode 100644 index b21b469a..00000000 --- a/design/marketing/web/wireframes/homepage.md +++ /dev/null @@ -1,342 +0,0 @@ -# Wireframe — Homepage (`/`) - -**Job:** get a technical visitor from "what is this" to a copied install command in under -30 seconds. Everything else on the page is for the visitor who did not copy it. - -**Primary CTA:** copyable install command (conversion event). -**Secondary CTA:** GitHub repo. -**There is no third CTA.** teemops.com sells nothing. The commercial side of the story -is one footer link to teem.cloud and that is the entire extent of it. - -There is no "Start Free Scan", no "No credit card required", and no login link. There is -nothing to log into. - ---- - -## Full-page structure - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ 1. NAV │ -│ 2. HERO ← install command + findings register │ -│ 3. PROOF STRIP ← 74 checks · 11 services · CIS · Apache │ -│ 4. THE PROBLEM ← scanners give you a report, not a queue │ -│ 5. DURABLE FINDINGS ← THE differentiator (milestone 2) │ -│ 6. HOW IT WORKS ← 3 steps, install → role → scan │ -│ 7. SCOPE A SCAN ← per-service + multi-region │ -│ 8. INSIGHTS ← group by service / benchmark │ -│ 9. FINAL CTA │ -│ 10. FOOTER ← carries the one Teem link │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Sections 5, 7 and 8 are new and are all milestone 2. - -**There is no "who runs it" or paid-options section.** An earlier draft had three cards -for managed hosting and support services; that is deleted. teemops.com is the project -site and the project is free — the company behind it gets one line in the footer, on the -Red Hat / Fedora split: the project site talks about the software, the company site -talks about the company. - -The old "Social proof — logos, testimonials" section is also deleted, not deferred: we -have no customers to name, and a row of grey placeholder logos reads worse than no -section at all. Repo signals carry that weight instead, in §3. - ---- - -## 1. Nav - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ [logo] TOPS Features How it works Docs │ -│ [ ★ Star on GitHub 1.2k ] │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -- **No Pricing item.** There is no pricing page — see [pricing.md](pricing.md) for what - happens at that route instead. A nav link named "Pricing" on a free project invites the - "so what's the catch" reflex we have nothing to answer with. -- No Login / Sign up. Replaced by the GitHub button as the persistent right-hand action. -- Star count is live from the GitHub API, cached; render the button without a count if - the call fails rather than blocking paint. -- Sticky on scroll. Below `md`, collapses to hamburger + GitHub button. - ---- - -## 2. Hero - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ │ │ -│ Find what's wrong in your │ ┌─────────────────────────────┐ │ -│ AWS account. Then fix it. │ │ ● ● ● Findings │ │ -│ │ ├─────────────────────────────┤ │ -│ Open-source AWS security │ │ [ All ▾ ][ S3 ▾ ][ CIS ▾ ] │ │ -│ scanning you run yourself. │ │ │ │ -│ 74 checks, every finding │ │ ▌CRIT S3 bucket is public │ │ -│ carries the fix, and the │ │ Block public access… │ │ -│ ones you've triaged stay │ │ cis-2.1.5 ● Open │ │ -│ triaged. │ │ ─────────────────────────── │ │ -│ │ │ ▌HIGH Root has no MFA │ │ -│ ┌────────────────────────────┐ │ │ Enable MFA on root… │ │ -│ │ $ bash <(curl -fsSL …) [⧉]│ │ │ cis-1.5 ⊘ Ignored │ │ -│ └────────────────────────────┘ │ │ ─────────────────────────── │ │ -│ Docker is the whole list. │ │ ▌HIGH RDS is public │ │ -│ │ │ Set PubliclyAccess… │ │ -│ [ ★ Star on GitHub ] Docs → │ │ cis-2.3.1 ✓ Resolved │ │ -│ │ └─────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -**This panel replaces the `78/100` Security Score mockup.** Deliberately: the score was -deleted in `a246323`, and the replacement should show the thing we actually built -instead of it — a findings register where each row has a severity, a remediation, a -benchmark tag and a **status that persists**. - -Notes: - -- The three visible statuses (Open / Ignored / Resolved) are the whole pitch for #90 in - one glance. Keep all three visible; do not show three Opens. -- `cis-2.1.5` style benchmark tags are #87 made visible. Use real rule IDs. -- The filter chips at the top are #85 / #87. They are decorative here, but they must - match the real UI's chips — this panel becomes a real screenshot as soon as we have - one, and it should not look like a downgrade when it does. -- Install command: one line, truncated with ellipsis, click-to-copy with a "Copied" - toast. **Copy is the conversion event** — instrument it. -- Headline avoids "misconfigurations" in position one. The old subhead - ("Find misconfigurations before attackers do") is fine as a meta description but - buries what is different about us. - -Below `lg`: panel drops below the copy, no truncation of the install command — it wraps -to two lines instead. Do not hide the install command on mobile; people screenshot it. - ---- - -## 3. Proof strip - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ 74 checks · 11 AWS services · CIS AWS Foundations · │ -│ Apache-2.0 · Docker Compose, nothing else │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Thin band, single row, no icons. All five are verifiable and all five are load-bearing -for a technical reader. Numbers come from the README and must be regenerated when the -rule set changes — flag in the content plan that `scan:validate-rules` output is the -source, not a hand-typed number. - ---- - -## 4. The problem - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Most scanners hand you a PDF. Then another one. │ -│ │ -│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │ -│ │ Every scan │ │ You triaged │ │ 400 findings, │ │ -│ │ starts from │ │ it last week. │ │ no idea which │ │ -│ │ zero │ │ It's back. │ │ 3 matter │ │ -│ └────────────────┘ └────────────────┘ └────────────────┘ │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Three cards, no icons needed. Each one is answered by a section below — §5 answers the -first two, §8 answers the third. Keep the ordering aligned. - ---- - -## 5. Durable findings — the differentiator - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ A finding is a record, not a row in a report │ -│ │ -│ ┌────────────────────────────┐ Scan on Mon: ▌HIGH Root MFA │ -│ │ │ → you mark Ignored │ -│ │ [ before / after │ "root is break- │ -│ │ rescan diagram ] │ glass only" │ -│ │ │ │ -│ │ same finding, same │ Scan on Fri: ▌HIGH Root MFA │ -│ │ record, status intact │ ⊘ still Ignored │ -│ │ │ │ -│ └────────────────────────────┘ Your triage survives. So does the │ -│ first-seen date. │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #81 and #90. This is the section to get right — it is the only claim on the page -that a competitor's free tier does not also make. - -- Left: simple two-state diagram, not a screenshot. A screenshot cannot show *time*. -- Right: concrete narrative with a real, defensible example (break-glass root account). -- Include the first-seen / last-seen line. "How long has this been open" is the question - a durable record can answer and a per-scan row cannot. -- Copy must not say "we track findings over time" — every vendor says that. Say what - breaks without it: *you re-triage the same thing every week*. - ---- - -## 6. How it works - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ ① Install ② Connect an account ③ Scan │ -│ ┌──────────────────┐ ┌──────────────────┐ ┌───────────────┐ │ -│ │ $ bash <(curl …) │ │ CloudFormation │ │ findings │ │ -│ │ │ │ grants a │ │ appear as they │ │ -│ │ Docker Compose. │ │ read-only │ │ are produced │ │ -│ │ No PHP, no DB. │ │ audit role │ │ │ │ -│ └──────────────────┘ └──────────────────┘ └───────────────┘ │ -│ │ -│ You don't need an AWS account to try it. │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -- Step 2 must say **read-only** in the step itself, not in small print. It is the first - objection a CTO has and answering it early is worth more than a trust badge. -- The "you don't need an AWS account to try it" line is from the README and is a genuine - friction remover. Keep it directly under the steps. -- Do **not** claim a total time here. See open question 3 in the README. - ---- - -## 7. Scope a scan - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Scan one service, not the whole benchmark │ -│ │ -│ ┌─────────────────────────────────────┐ Chasing one S3 change? │ -│ │ New scan │ Scan S3. │ -│ │ Account [ prod-1234 ▾ ] │ │ -│ │ Profile [ CIS Foundations ▾ ] │ Regions run in parallel, │ -│ │ Services [✓ S3 ] [ IAM ] [ EC2 ] │ so more regions doesn't │ -│ │ [ RDS ] [ +7 more ] │ mean a longer wait. │ -│ │ [ Start scan ] │ │ -│ └─────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #84 and #92. Becomes a screenshot of the real New Scan modal once captured. -The parallel-regions line is the only place multi-region gets airtime on the homepage — -it is an implementation win, not a buying reason, so one sentence is the right budget. - ---- - -## 8. Insights - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Know which three things matter │ -│ │ -│ ┌───────────────────────────┐ ┌───────────────────────────┐ │ -│ │ Findings by service │ │ Findings by benchmark │ │ -│ │ S3 ███████ 42 ▌12 ▌8 │ │ CIS 1.x ████ 18 │ │ -│ │ IAM █████ 31 ▌ 9 ▌4 │ │ CIS 2.x ███████ 40 │ │ -│ │ EC2 ███ 19 ▌ 2 ▌7 │ │ CIS 3.x ██ 11 │ │ -│ └───────────────────────────┘ └───────────────────────────┘ │ -│ │ -│ Click through to a filtered, shareable list → │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Ships #88, #89, and — via the caption — #83 and #85/#87. "Shareable" is the user-facing -value of filters living in the URL; say that, not "URL state". - -**Note the section has no total number and no score.** Resist adding a headline metric -here; that instinct is what produced the score in the first place. - ---- - -## 9. Final CTA - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ One command. Docker is the only prerequisite. │ -│ │ -│ ┌──────────────────────────────────────────┐ │ -│ │ $ bash <(curl -fsSL …/install.sh) [⧉] │ │ -│ └──────────────────────────────────────────┘ │ -│ │ -│ Read the script first → ★ Star on GitHub │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -"Read the script first" links to the `curl -o install.sh` variant in the docs. Offering -it is a trust signal that costs nothing and lands with exactly the audience we want. - ---- - -## 10. Footer — and the one Teem link - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ Product Docs Project Legal │ -│ Features Install GitHub Licence │ -│ How it works Scanning AWS Issues Trademark │ -│ Insights Configuration Releases Privacy │ -│ │ -│ ────────────────────────────────────────────────────────────────── │ -│ │ -│ Teem is the company behind the open source software. │ -│ For AWS security auditing, view their website → teem.cloud │ -│ │ -│ ────────────────────────────────────────────────────────────────── │ -│ TOPS is free and open source under Apache-2.0. [Apache-2.0] │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -**This band is the only commercial mention on the entire site.** Not a card, not a -banner, not a CTA — a sentence and a link, below the fold of every page, in body text -weight. Anyone who needs a vendor will find it; nobody who just wants the software has -to step around it. - -The model is Red Hat: the project is genuinely free forever and stays that way, and a -company exists behind it for organisations that need stability, help with setup, or -someone accountable for running it. That whole proposition lives on teem.cloud. It does -**not** get explained here — the moment teemops.com starts describing support offerings, -it stops being a project site. - -Rules for this band, which should be treated as constraints and not preferences: - -- **One placement, site-wide.** Footer only. It does not also appear in the nav, the - hero, a mid-page section, or a banner. -- **No commercial verbs.** No "get support", "talk to sales", "enterprise", "pricing", - "book a demo". The link text is the company name and what it is. -- **`rel="noopener"`, opens in a new tab.** A visitor leaving for teem.cloud should not - lose the install command they were about to copy. -- **Wording is fixed**, product-owner supplied: *"Teem is the company behind the open - source software. For AWS security auditing, view their website."* Copywriting may fix - punctuation and nothing else. -- The Apache-2.0 line sits *below* the Teem line, so the last thing on every page is the - free-software statement rather than the company. - -The rest of the footer is standard. The "Company" column from the old design is renamed -**Project** and carries GitHub / Issues / Releases — because that is what the community -around this software actually is. Legal keeps the licence link and the trademark notice -(`TRADEMARK.md` exists, and a marketing site is the place it actually matters). - ---- - -## Assets needed - -| Asset | Blocking? | Note | -| --- | --- | --- | -| Findings list screenshot | Hero — yes | Needs realistic data with all 3 statuses visible | -| New Scan modal screenshot | §7 — no | Wireframe box is adequate for review | -| Insights screenshot | §8 — no | Same | -| Rescan diagram | §5 — yes | Custom illustration; nothing existing works | -| Live GitHub star count | Nav — no | Degrade to plain button | - -## Deleted from the current homepage - -- Security Score panel (`../html/index.html:104`) — feature no longer exists -- "Start Free Scan" CTAs — nothing to sign up for -- "No credit card required. Free tier available forever." — implies a paid SaaS tier above it -- Social proof / customer logo section — no customers to name -- Pricing teaser with $/mo — there is no pricing -- "Pricing" nav item — see [pricing.md](pricing.md) -- The three-card "who runs it" block from the first draft of this wireframe — replaced by - the single footer line in §10 diff --git a/design/marketing/web/wireframes/html/features.html b/design/marketing/web/wireframes/html/features.html deleted file mode 100644 index 6b63f4ae..00000000 --- a/design/marketing/web/wireframes/html/features.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - -Wireframe — teemops.com features - - - - - - -
- - -
- §1 · Hero + jump nav -

Everything TOPS does

-

74 checks across 11 AWS services. Self-hosted. Apache-2.0.

-
-

- Findings  ·  Scanning  ·  Filtering  ·  Remediation  ·  - Insights  ·  Teams -

-
- Note 1 — this page is scanned, not read - The reader has decided we're interesting and is now checking whether we do the one specific - thing they need. Optimise for someone using ⌘F. Sticky jump nav under the main nav on - lg+; drop it below md rather than stacking two sticky bars. -
-
- Note 2 — reorganised, not edited - The current page (../pages/features.md, 333 lines) is a generic CSPM feature list: - scanning, compliance, multi-account, alerts, remediation, reporting, integrations. Three of - those sections describe things that don't exist or are now wrong. This is organised around what - we actually ship. -
-
- - -
- §2 · Durable findings -

Findings that persist

-

One record per resource and rule — not one row per scan.

- -
-
-
-
CRIT
-
-
S3 bucket allows public read
-
arn:aws:s3:::acme-assets
-
First seen 12 Jun · Last seen 2 Aug · 51 days open
-
- cis-2.1.5S3 - Status: ● Open -
-
-
Fix: Enable Block Public Access on the bucket.
-
-
-
-
- -
    -
  • Mark resolved or ignored — it stays that way through the next scan
  • -
  • First-seen and last-seen on every finding
  • -
  • Reappears automatically if the misconfiguration comes back
  • -
- -
- Note 3 — the anatomy figure - Ships #81 and #90. Every element on this card is a separate capability, labelled once; the - sections below refer back to it rather than re-explaining. -
-
- Note 4 — "51 days open" is the number that sells this - It is only computable because a finding is a durable record (#81). A per-scan row cannot - produce it. -
-
- - -
- §3 · Scanning -

Scan what you need, when you need it

-
-
-

Whole benchmark

-

CIS AWS Foundations, or the general "basic" profile.

-
-
-

One service

-

Changed one S3 policy? Scan S3 and get an answer in a - fraction of the time.

-
-
-

Regions run in parallel. A ten-region account isn't ten times the wait.

- -

Coverage

- - - - - - - - -
ServiceChecksServiceChecks
S3nIAMn
EC2nRDSn
CloudTrailnKMSn
LambdanDynamoDBn
ELBv2nSNSn
SQSn11 services · 74 checks
-

See every check → docs

- -
- Note 5 — the coverage table is the ⌘F target - Highest-value block on the page for an evaluator. Per-service counts must be - generated from the rule JSON via scan:validate-rules, never typed. - A stale count here is exactly the small inaccuracy that loses a technical buyer. -
-
- Note 6 — link out, don't inline - Full listing of all 74 checks belongs in the docs, not on this page. -
-
- - -
- §4 · Filter and slice -

Cut 400 findings down to the 8 you're working on

- -
-
-
- Account: prod ▾ - Service: S3 ▾ - Benchmark: CIS 2.x ▾ - Severity: Critical ▾ - Status: Open ▾ - 12 results -
-
-
- -

- /findings?service=s3&benchmark=cis&status=open -

-

- ↑ every filter is in the URL — bookmark it, paste it in Slack, send it to the person who owns S3 -

- -
- Note 7 — render the URL as visible monospace, not a caption - Ships #85, #87, #83. The URL is the section; it should not be styled as an aside. -
-
- Note 8 — one sentence on why benchmark filtering works - Findings record which benchmark raised them (a74a6c3), so a compliance question has - a direct answer. -
-
- - -
- §5 · Remediation -

Every finding tells you how to fix it

-
-
-

In the list

-
-
HIGH
-
-
RDS instance is publicly accessible
-
Set PubliclyAccessible to false
-
-
-

One line. No click needed.

-
-
-

On the finding

-
    -
  1. Open the RDS console
  2. -
  3. Modify → Connectivity
  4. -
  5. Public access → No
  6. -
  7. Apply immediately
  8. -
-

AWS docs →

-
-
-

Step-by-step guidance on every critical and high finding.

- -
- Note 9 — the split is the real product behaviour - Ships #82. A one-liner everywhere, full steps on critical and high. Do not - imply step-by-step exists on all 74 checks — the README is precise about this and the site must - match it. -
-
- - -
- §6 · Insights -

Where the problems actually are

-
-
-

By service

-

With a severity breakdown per service, so "42 in S3" becomes - "12 critical in S3".

-
-
-

By benchmark

-

Which controls are failing, and how badly.

-
-
-

- Also: findings trend over a period, severity distribution, remediation rate. -

-
- Note 10 — the "also" line is table stakes and gets one line - Ships #88 and #89. Trend / distribution / remediation-rate already existed and must not get - equal billing with the two groupings. -
-
- Note 11 — no score, no grade, no single health number anywhere on this page -
-
- - -
- §7 · Teams and isolation -

Built multi-tenant from the schema up

-

Organisations · team roles · every query scoped by organisation.

-

Run one instance for several clients, or several teams, without one seeing another's findings.

-
- Note 12 — short, and aimed at agencies and MSPs - A real segment for a self-hosted scanner. It is genuinely enforced rather than aspirational, so - we can state it flatly. -
-
- - -
- §8 · What we don't do -

What TOPS doesn't do (yet)

-
    -
  • Azure or GCP — AWS only
  • -
  • Auto-remediation — we tell you the fix, you apply it
  • -
  • Real-time alerting / webhooks — scans are on demand
  • -
  • Agent-based runtime monitoring — this is config scanning
  • -
-

Roadmap → github.com/teemops/tops

-
- Note 13 — recommend keeping this section - It disqualifies bad-fit visitors before they install and bounce, it is unusual enough to be - memorable, and on an open-source project it reads as confidence. It also lets us delete the - current page's "Real-time Alerts" and "Integrations (future)" sections honestly instead of - leaving them as vapour. -
-
- Note 14 — only an asset while it's accurate - Verify every line against the roadmap before shipping. -
-
- - -
- §9 · CTA -
-
- $ bash <(curl -fsSL https://raw.githubusercontent.com/teemops/tops/develop/install.sh) - ⧉ Copy -
-

Read the script first →     ★ Star on GitHub

-
-
- Note 15 — no paid alternative offered, here or anywhere on this page - Same block as homepage §9. The only commercial mention on the site is - the footer line in homepage §10. -
-
- - -
- Removed from the current features page -
- Deleted -
    -
  • Three "Score" tiles (../html/features.html:285, 303, 321) — feature removed - in a246323
  • -
  • "Real-time Alerts" section — does not exist; now one line in §8
  • -
  • "Integrations (future)" section — does not exist; now one line in §8
  • -
  • "Reporting & Exports" as a headline section — demote to a line unless we can - screenshot it
  • -
  • All "Start Free Scan" CTAs
  • -
-
-
- -
- - - - - diff --git a/design/marketing/web/wireframes/html/index.html b/design/marketing/web/wireframes/html/index.html deleted file mode 100644 index a2d0b3e2..00000000 --- a/design/marketing/web/wireframes/html/index.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - -Wireframe — teemops.com homepage - - - - - - -
- - -
- §1 · Nav -
-
▣ TOPS
-
Features    How it works    Docs
-
★ Star on GitHub  1.2k
-
-
- Note 1 — what's missing is the point - No Pricing item and no Login / Sign up. There is nothing to sign up for, and a - nav link named "Pricing" on a free project invites the "so what's the catch" reflex we have - nothing to answer with. The GitHub button is the persistent right-hand action instead. - Sticky on scroll; collapses to hamburger + GitHub button below md. -
-
- Note 2 — star count - Live from the GitHub API, cached. Render the button without a count if the call fails rather - than blocking paint. -
-
- - -
- §2 · Hero -
-
-

Find what's wrong in your AWS account. Then fix it.

-

- Open-source AWS security scanning you run yourself. 74 checks, every finding carries the - fix, and the ones you've triaged stay triaged. -

-
- $ bash <(curl -fsSL https://raw.githubusercontent.com/teemops/tops/develop/install.sh) - ⧉ Copy -
-

Docker is the whole list.

-

- ★ Star on GitHub -   Docs → -

-
- -
-
Findings
-
-
- All accounts ▾ - S3 ▾ - CIS ▾ -
-
-
CRIT
-
-
S3 bucket allows public read
-
Enable Block Public Access on the bucket
-
cis-2.1.5● Open
-
-
-
-
HIGH
-
-
Root account has no MFA
-
Enable MFA on the root user
-
cis-1.5⊘ Ignored
-
-
-
-
HIGH
-
-
RDS instance is publicly accessible
-
Set PubliclyAccessible to false
-
cis-2.3.1✓ Resolved
-
-
-
-
-
- -
- Note 3 — this panel replaces the security score - The current hero is built around a 78/100 Security Score - (../html/index.html:104). That feature was deleted in a246323 - (issue #91 — pinned at 0, could not improve). The replacement shows what we built - instead of it: a findings register where every row has a severity, a remediation, a - benchmark tag, and a status that persists. -
-
- Note 4 — three different statuses, deliberately - Open / Ignored / Resolved on screen at once is the entire pitch for issue #90 in one - glance. Do not let this become three Opens. The cis-* tags are issue #87 made - visible; use real rule IDs. -
-
- Note 5 — the filter chips must match the real UI - They are decorative here, but this panel becomes a real screenshot as soon as one is captured, - and it must not look like a downgrade when it does. -
-
- Note 6 — the copy button is the conversion event - Click-to-copy with a "Copied" toast. Instrument it. Below lg the panel drops under - the copy and the command wraps to two lines — do not hide it on mobile, people screenshot it. -
-
- - -
- §3 · Proof strip -

- 74 checks  ·  11 AWS services  ·  CIS AWS Foundations  ·  - Apache-2.0  ·  Docker Compose, nothing else -

-
- Note 7 — all five are verifiable - Thin band, single row, no icons. Numbers come from the rule set, not from a copywriter — - scan:validate-rules is the source and they must be regenerated when rules change. -
-
- - -
- §3b · Free. Forever. — decision pending -
-

Free. Forever.

-

- Apache-2.0. Every check, unlimited AWS accounts, unlimited users. No trial, no seats, no - edition above this one, and no feature we've held back to sell you later. -

- Read the licence -
-
- Note 8 — this is the open question - /pricing 301s here (#free). Whether the band earns homepage space is - the last structural decision in this set — see ../pricing.md. Recommendation: keep - it, keep it small. Every visitor arriving from a commercial CSPM carries the assumption that - there is a catch, and one unambiguous paragraph is cheaper than losing them to that suspicion. - It must read as a statement of fact, not a sales counter-argument: no comparison table, no - "unlike other vendors", no exclamation marks. -
-
- - -
- §4 · The problem -

Most scanners hand you a PDF. Then another one.

-
-

Every scan starts from zero

-

You triaged it last week. It's back.

-

400 findings, no idea which 3 matter

-
-
- Note 9 — keep the ordering aligned - §5 answers the first two cards, §8 answers the third. If the cards get reordered in copy, the - sections move with them. -
-
- - -
- §5 · Durable findings — the differentiator -

A finding is a record, not a row in a report

-
-
Diagram — same finding across two scans,
status intact. Custom illustration.
-
-

Scan on Monday
- HIGH · Root account has no MFA
- → you mark it Ignored: "root is break-glass only"

-

Scan on Friday
- HIGH · Root account has no MFA
- → still Ignored

-

Your triage survives. So does the first-seen date.

-
-
-
- Note 10 — the one claim a competitor's free tier can't make - Ships issues #81 and #90. This is the section to get right. A diagram, not a screenshot — a - screenshot cannot show time. -
-
- Note 11 — copy constraint - Must not say "we track findings over time"; every vendor says that. Say what breaks without it: - you re-triage the same thing every week. Keep the first-seen / last-seen line — "how - long has this been open" is the question a durable record answers and a per-scan row cannot. -
-
- - -
- §6 · How it works -
-
-

① Install

-

$ bash <(curl …)
Docker Compose. No PHP, no database.

-
-
-

② Connect an account

-

A CloudFormation stack grants TOPS a read-only audit role.

-
-
-

③ Scan

-

Findings appear as they are produced.

-
-
-

You don't need an AWS account to try it.

-
- Note 12 — "read-only" goes in the step, not the small print - It is the first objection a CTO has, and answering it early is worth more than a trust badge. -
-
- Note 13 — no total time claimed here - 7494959 instrumented scan phases to baseline where the time goes. Do not put a - number on this page until the instrumentation supports one. -
-
- - -
- §7 · Scope a scan -

Scan one service, not the whole benchmark

-
-
-
New scan
-
-

Account

-
prod-1234 ▾
-

Profile

-
CIS AWS Foundations ▾
-

Services

-
- ✓ S3IAMEC2 - RDS+7 more -
-

Start scan

-
-
-
-

Chasing one S3 change? Scan S3.

-

Regions run in parallel, so more regions doesn't mean a longer wait.

-
-
-
- Note 14 — one sentence is the right budget for multi-region - Ships #84 and #92. Parallel regions is an implementation win, not a buying reason. Becomes a - screenshot of the real New Scan modal once captured. -
-
- - -
- §8 · Insights -

Know which three things matter

-
-
-

Findings by service

-
    -
  • S342
  • -
  • IAM31
  • -
  • EC219
  • -
-

…each with a severity breakdown

-
-
-

Findings by benchmark

-
    -
  • CIS 1.x18
  • -
  • CIS 2.x40
  • -
  • CIS 3.x11
  • -
-
-
-

Click through to a filtered, shareable list →

-
- Note 15 — no total, no score, no headline metric - Ships #88, #89 and — via the caption — #83 and #85/#87. Resist adding a single health number - here; that instinct is what produced the security score in the first place. -
-
- Note 16 — say "shareable", not "URL state" - Shareable is the user-facing value of filters living in the URL. -
-
- - -
- §9 · Final CTA -
-

One command. Docker is the only prerequisite.

-
- $ bash <(curl -fsSL https://raw.githubusercontent.com/teemops/tops/develop/install.sh) - ⧉ Copy -
-

Read the script first →     ★ Star on GitHub

-
-
- Note 17 — "read the script first" is a trust signal that costs nothing - Links to the curl -o install.sh variant in the docs. Lands with exactly the - audience we want. -
-
- - -
- §10 · Footer — and the one Teem link -
-

Product

Features
How it works
Insights

-

Docs

Install
Scanning AWS
Configuration

-

Project

GitHub
Issues
Releases

-

Legal

Licence
Trademark
Privacy

-
- -
- -

- Teem is the company behind the open source software.
- For AWS security auditing, view their website → - teem.cloud -

- -
- -

- TOPS is free and open source under Apache-2.0.   Apache-2.0 -

- -
- Note 18 — this band is the only commercial mention on the entire site - Not a card, not a banner, not a CTA — a sentence and a link, below the fold of every page, in - body-text weight. Anyone who needs a vendor will find it; nobody who just wants the software - has to step around it. -
-
- Note 19 — treat these as constraints, not preferences - One placement, site-wide — footer only, never nav/hero/mid-page/banner. - No commercial verbs — no "get support", "talk to sales", "enterprise", - "pricing", "book a demo". rel="noopener", new tab — a visitor - leaving for teem.cloud must not lose the install command they were about to copy. - Wording is fixed (product-owner supplied); copywriting may fix punctuation and - nothing else. Apache-2.0 sits below it, so the last thing on every page is the - free-software statement rather than the company. -
-
- Note 20 — the Red Hat split - Forever-free software here; a company behind it for customers who need stability or help with - setup and management. Everything about that lives on teem.cloud and is not explained - here. Red Hat works because fedoraproject.org does not sell RHEL — the moment teemops.com - describes support offerings, every free claim on the site reads as a funnel. The old "Company" - footer column is renamed Project for the same reason. -
-
- - -
- Removed from the current homepage -
- Deleted -
    -
  • Security Score panel (../html/index.html:104) — the feature no longer exists
  • -
  • All "Start Free Scan" CTAs — nothing to sign up for
  • -
  • "No credit card required. Free tier available forever." — implies a paid tier above it
  • -
  • Social proof / customer logo section — no customers to name; a row of grey placeholder - logos reads worse than no section at all
  • -
  • Pricing teaser with $/mo, and the "Pricing" nav item — there is no pricing
  • -
  • The three-card "who runs it" block from the first draft of this wireframe — replaced by - the single footer line in §10
  • -
-
-
- - -
- Assets still needed - - - - - - - -
AssetBlocking?Note
Findings list screenshot§2 — yesNeeds realistic data with all three statuses visible
Rescan diagram§5 — yesCustom illustration; nothing existing works
New Scan modal screenshot§7 — noWireframe box is adequate for review
Insights screenshot§8 — noSame
Live GitHub star count§1 — noDegrade to a plain button
-
- -
- - - - - diff --git a/design/marketing/web/wireframes/html/pricing.html b/design/marketing/web/wireframes/html/pricing.html deleted file mode 100644 index 40ff4482..00000000 --- a/design/marketing/web/wireframes/html/pricing.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - -Wireframe — /pricing is deleted - - - - - - -
- -
- Recommendation -

Delete the pricing page. Keep the URL.

-

- teemops.com sells nothing. No tiers, no managed-hosting cards, no service offers, no - "talk to us". The software is Apache-2.0 and stays that way, and the company behind it gets - exactly one sentence in the footer of every page. -

-

- This page exists only because /pricing is currently in the nav and the sitemap, - and "deleted the page" is not a complete answer for a URL people will still type, search for - and link to. -

-
- -
- What replaces it -

teemops.com/pricing  →  301  →  teemops.com/#free

-

- A permanent redirect to a short "Free. Forever." band on the homepage, sitting - between the proof strip (§3) and the problem section (§4). -

- -
-
-

Free. Forever.

-

- Apache-2.0. Every check, unlimited AWS accounts, unlimited users. No trial, no seats, no - edition above this one, and no feature we've held back to sell you later. -

- Read the licence -
-
- -
- Note 1 — four lines and a link - That is the whole answer. Giving it a dedicated page would make it look like a longer answer - than it is. -
-
- Note 2 — why keep the route at all - "is X free" and "X pricing" are the highest-intent sceptical queries an open-source project - gets, and they are exactly the ones a commercial competitor's comparison page will try to own. - Landing them on a two-sentence "yes, actually free" costs one redirect rule. -
-
- Note 3 — the open judgement call - Does this band belong on the homepage at all? The hero already says open-source and - self-hosted, and §3 already shows the Apache-2.0 badge; an argument exists that a whole band - restating it protests too much. Recommendation: keep it, keep it small. If it - is cut, point the redirect at the features-page FAQ instead of #free, so the URL - still lands somewhere that answers the question. -
-
- -
- The Red Hat framing — where each half is said -

Product owner, 2026-08-02:

-
- We provide open source, forever free software, but we have a company behind this so if a - customer needs stability and a different level of support during setup or management of the - software, Teem will support. -
- - - - - - -
ClaimSaid on
The software is free, forever, no held-back featuresteemops.com — loudly, repeatedly
A company stands behind itteemops.com — one footer sentence, once
What that company will do for you, and what it coststeem.cloud only
- -
- Note 4 — the discipline this needs - Red Hat works because fedoraproject.org does not sell RHEL. The moment teemops.com starts - describing support tiers, response times or engagement models, every free claim on the site - reads as a funnel. The footer link is load-bearing because it is the only one — it is - a door, not a pitch. -
-
- Note 5 — so, explicitly none of these - No support page, no enterprise page, no contact-sales form, no "need help?" callout, no - comparison table with a paid column. People looking to spend money are good at finding where to - spend it. -
-
- -
- Consequences for the rest of the site - - - - - - - - - -
File / elementAction
Nav "Pricing & support" itemRemove → Features · How it works · Docs + GitHub button
Homepage three-card paid blockRemove (was in the first draft of this set)
../pages/pricing.md — 230 linesDelete, not rewrite
../html/pricing.html — 588 linesDelete
../pricing-strategy.md — 431 linesMove, don't delete — only written-down SMB segment analysis; plausible input for teem.cloud
../content-plan.md site structureDrop /pricing; drop /contact on the same logic
"free tier" wording across ../pages/*.mdReword — "free tier" implies a paid tier above it. The word is just free
-
- Note 6 — /contact is a sales channel wearing a different hat - GitHub issues is the contact channel for a project; teem.cloud can own the rest. Flagged, not - actioned in this set. -
-
- -
- Removed from the current pricing page -
- Deleted -
    -
  • Free / Starter ($149) / Pro ($449) / Business tiers — priced a SaaS we are not shipping
  • -
  • "20% off annual" — no subscription product to discount
  • -
  • Per-tier limits on AWS accounts, scan frequency, check count, history, users — none of - these limits exist in the software, and inventing them contradicts the licence
  • -
  • "Not competing on price with DIY/open source" positioning — we are the open - source
  • -
  • The managed-hosting and support-services cards drafted earlier in this wireframe set — - those belong on teem.cloud, which is out of scope for - design/marketing/web/
  • -
-
-
- -
- - - - - diff --git a/design/marketing/web/wireframes/html/wireframe.css b/design/marketing/web/wireframes/html/wireframe.css deleted file mode 100644 index c92bcde1..00000000 --- a/design/marketing/web/wireframes/html/wireframe.css +++ /dev/null @@ -1,222 +0,0 @@ -/* Low-fidelity wireframe styling for the teemops.com redraw. - Greyscale on purpose — this is structure and message, not visual design. - Self-contained: no CDN, no fonts, no network. Opens offline from the filesystem. */ - -:root { - --ink: #1a1a1a; - --mid: #6b6b6b; - --faint: #9a9a9a; - --line: #c2c2c2; - --fill: #f1f1f1; - --fill-2: #e4e4e4; - --paper: #fff; - --note: #0b57d0; - --note-bg: #eef3fd; - --note-line: #b9cdf3; - --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; - --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; -} - -* { box-sizing: border-box; } - -body { - margin: 0; - padding: 56px 0 80px; - background: #d9d9d9; - color: var(--ink); - font: 400 15px/1.55 var(--sans); -} - -/* ---------- wireframe chrome (not part of the design) ---------- */ - -.wf-bar { - position: fixed; inset: 0 0 auto 0; z-index: 100; - display: flex; align-items: center; gap: 4px; flex-wrap: wrap; - padding: 8px 14px; - background: var(--ink); color: #fff; - font: 500 12px/1 var(--mono); -} -.wf-bar strong { font-weight: 700; margin-right: 10px; letter-spacing: .04em; } -.wf-bar a { - color: #fff; text-decoration: none; opacity: .62; - padding: 5px 9px; border-radius: 4px; -} -.wf-bar a:hover { opacity: 1; background: #ffffff1f; } -.wf-bar a[aria-current="page"] { opacity: 1; background: #ffffff2e; } -.wf-bar button { - margin-left: auto; cursor: pointer; - padding: 5px 10px; border: 1px solid #ffffff4d; border-radius: 4px; - background: none; color: #fff; font: 500 12px/1 var(--mono); -} -.wf-bar button:hover { background: #ffffff1f; } - -.page { - max-width: 1080px; margin: 0 auto; padding: 0 16px; -} - -/* Each section gets a labelled frame so reviewers can cite "§5" */ -.sec { - position: relative; - margin: 26px 0; - padding: 40px 34px 34px; - background: var(--paper); - border: 1px solid var(--line); -} -.sec > .tag { - position: absolute; top: 0; left: 0; - padding: 4px 10px; - background: var(--ink); color: #fff; - font: 600 10px/1.4 var(--mono); letter-spacing: .08em; text-transform: uppercase; -} -.sec.tight { padding-top: 34px; } - -/* ---------- generic low-fi primitives ---------- */ - -h1, h2, h3, h4 { margin: 0 0 12px; line-height: 1.2; font-weight: 700; } -h1 { font-size: 34px; } -h2 { font-size: 25px; } -h3 { font-size: 17px; } -h4 { font-size: 14px; text-transform: uppercase; letter-spacing: .06em; color: var(--mid); } -p { margin: 0 0 12px; } -p.lede { font-size: 17px; color: var(--mid); } -.center { text-align: center; } -.muted { color: var(--mid); } -.small { font-size: 13px; } -.tiny { font-size: 11.5px; } - -.row { display: flex; gap: 18px; flex-wrap: wrap; } -.row > * { flex: 1 1 220px; min-width: 0; } -.split { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; align-items: center; } -.cols-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; } -.cols-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; } -@media (max-width: 860px) { - .split, .cols-3, .cols-2 { grid-template-columns: 1fr; } - .sec { padding: 38px 18px 24px; } - h1 { font-size: 27px; } -} - -.box { - padding: 16px; - border: 1px solid var(--line); - background: var(--paper); -} -.box.fill { background: var(--fill); } -.box.dash { border-style: dashed; } - -/* placeholder for imagery we don't have yet */ -.ph { - display: flex; align-items: center; justify-content: center; - min-height: 150px; padding: 16px; text-align: center; - border: 1px dashed var(--faint); - color: var(--faint); - font: 500 12px/1.5 var(--mono); - background: - linear-gradient(to top right, transparent calc(50% - .5px), var(--faint) 50%, transparent calc(50% + .5px)), - linear-gradient(to bottom right, transparent calc(50% - .5px), var(--faint) 50%, transparent calc(50% + .5px)), - var(--fill); -} -.ph span { padding: 4px 8px; background: var(--fill); } - -.btn { - display: inline-block; padding: 11px 20px; - border: 1.5px solid var(--ink); background: var(--ink); color: #fff; - font: 600 14px/1 var(--sans); text-decoration: none; -} -.btn.ghost { background: none; color: var(--ink); } -.btn.sm { padding: 7px 12px; font-size: 12.5px; } - -/* the install command — the primary conversion element on the site */ -.cmd { - display: flex; align-items: center; gap: 10px; - padding: 13px 14px; - border: 1.5px solid var(--ink); background: var(--fill); - font: 500 13px/1.3 var(--mono); - overflow: hidden; -} -.cmd code { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.cmd .copy { - flex: none; padding: 4px 9px; - border: 1px solid var(--ink); background: var(--paper); - font: 600 11px/1.3 var(--mono); -} -@media (max-width: 860px) { .cmd code { white-space: normal; } } - -/* app-UI chrome mimic, used in hero + product panels */ -.app { - border: 1px solid var(--ink); background: var(--paper); -} -.app > .bar { - display: flex; align-items: center; gap: 6px; - padding: 8px 10px; border-bottom: 1px solid var(--line); background: var(--fill); - font: 600 11px/1 var(--mono); color: var(--mid); -} -.app > .bar i { width: 9px; height: 9px; border: 1px solid var(--faint); border-radius: 50%; } -.app > .bar em { margin-left: auto; font-style: normal; } -.app > .body { padding: 12px; } - -.chips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; } -.chip { - padding: 4px 9px; border: 1px solid var(--line); background: var(--fill); - font: 500 11px/1.3 var(--mono); color: var(--mid); white-space: nowrap; -} -.chip.on { border-color: var(--ink); color: var(--ink); background: var(--paper); } - -/* a findings row — severity is a weight, never a colour, in a wireframe */ -.finding { - display: flex; gap: 10px; - padding: 10px 0; border-top: 1px solid var(--line); -} -.finding:first-child { border-top: 0; } -.finding .sev { - flex: none; width: 62px; - font: 700 10px/1.6 var(--mono); letter-spacing: .04em; - border-left: 4px solid var(--ink); padding-left: 7px; -} -.finding .sev.s2 { border-left-color: var(--mid); } -.finding .sev.s3 { border-left-color: var(--line); } -.finding .meta { flex: 1; min-width: 0; } -.finding .title { font-weight: 600; font-size: 13.5px; } -.finding .fix { font-size: 12.5px; color: var(--mid); } -.finding .tags { margin-top: 4px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; } -.status { font: 600 11px/1.4 var(--mono); } - -/* simple bar chart for the insights blocks */ -.bars { margin: 0; padding: 0; list-style: none; font: 500 12px/1 var(--mono); } -.bars li { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; } -.bars .k { width: 74px; flex: none; color: var(--mid); } -.bars .b { height: 12px; background: var(--fill-2); border: 1px solid var(--line); } -.bars .n { color: var(--mid); } - -table.wf { width: 100%; border-collapse: collapse; font-size: 13.5px; } -table.wf th, table.wf td { padding: 9px 10px; border-bottom: 1px solid var(--line); text-align: left; } -table.wf th { font: 600 11px/1.4 var(--mono); text-transform: uppercase; letter-spacing: .05em; color: var(--mid); } -table.wf td.c, table.wf th.c { text-align: center; } - -ul.ticks { margin: 0; padding: 0; list-style: none; } -ul.ticks li { padding: 4px 0 4px 22px; position: relative; font-size: 13.5px; } -ul.ticks li::before { content: "✓"; position: absolute; left: 0; color: var(--mid); } -ul.ticks li.no::before { content: "✗"; } - -/* ---------- annotations (reviewer notes, toggleable) ---------- */ - -.note { - margin: 14px 0 0; - padding: 11px 13px; - border-left: 3px solid var(--note); - background: var(--note-bg); - color: #17335f; - font-size: 13px; -} -.note b { color: var(--note); font: 700 10.5px/1.6 var(--mono); letter-spacing: .07em; text-transform: uppercase; display: block; } -.note a { color: var(--note); } -.note code { font: 500 12px/1.4 var(--mono); background: #ffffffb3; padding: 1px 4px; } -body.no-notes .note { display: none; } - -.gone { - margin: 14px 0 0; padding: 11px 13px; - border: 1px dashed var(--faint); background: repeating-linear-gradient( - 135deg, transparent 0 8px, #00000008 8px 16px); - color: var(--mid); font-size: 13px; -} -.gone b { display: block; font: 700 10.5px/1.6 var(--mono); letter-spacing: .07em; text-transform: uppercase; } -body.no-notes .gone { display: none; } diff --git a/design/marketing/web/wireframes/pricing.md b/design/marketing/web/wireframes/pricing.md deleted file mode 100644 index 26a85417..00000000 --- a/design/marketing/web/wireframes/pricing.md +++ /dev/null @@ -1,126 +0,0 @@ -# Wireframe — the pricing page, and why there isn't one - -**Recommendation: delete the pricing page. Keep the URL.** - -teemops.com sells nothing. There are no tiers, no managed hosting cards, no service -offers, no "talk to us". The software is free under Apache-2.0 and stays that way, and -the company behind it gets exactly one sentence in the footer of every page — specified -in [homepage.md](homepage.md) §10. - -This file exists because `/pricing` is currently in the nav and in the sitemap, and -"deleted the page" is not a complete answer for a URL that people will still type, -search for, and link to. - ---- - -## What replaces it - -``` -teemops.com/pricing → 301 → teemops.com/#free -``` - -A permanent redirect to a short **"Free. Forever."** band on the homepage, sitting -between the proof strip (§3) and the problem section (§4). - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ │ -│ Free. Forever. │ -│ │ -│ Apache-2.0. Every check, unlimited AWS accounts, unlimited users. │ -│ No trial, no seats, no edition above this one, and no feature │ -│ we've held back to sell you later. │ -│ │ -│ [ Read the licence ] │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -Four lines and a link. That is the whole answer, and giving it a dedicated page would -make it look like a longer answer than it is. - -Why keep the route at all: "is X free" and "X pricing" are the highest-intent sceptical -queries an open-source project gets, and they are the ones a commercial competitor's -comparison page will try to own. Landing them on a two-sentence "yes, actually free" -costs one redirect rule. - -**Add this band to the homepage wireframe when this file is signed off.** It is not -drawn into [homepage.md](homepage.md) yet, because whether it earns above-the-fold- -adjacent space is the one open judgement call here — see below. - ---- - -## The Red Hat framing, and where it lives - -Product owner, 2026-08-02: - -> We provide open source, forever free software, but we have a company behind this so if -> a customer needs stability and a different level of support during setup or management -> of the software, Teem will support. - -That is the right model and the wireframes adopt it. The part worth being disciplined -about is **where each half of it is said**: - -| Claim | Said on | -| --- | --- | -| The software is free, forever, no held-back features | teemops.com — loudly, repeatedly | -| A company stands behind it | teemops.com — one footer sentence, once | -| What that company will do for you, and what it costs | **teem.cloud only** | - -Red Hat works because fedoraproject.org does not sell RHEL. The moment teemops.com -starts describing support tiers, response times or engagement models, every free claim -on the site reads as a funnel. The footer link is load-bearing precisely *because* it is -the only one — it is a door, not a pitch. - -So: no support page, no enterprise page, no contact-sales form, no "need help?" callout, -no comparison table with a paid column. If a visitor needs a vendor, one footer link is -enough — people looking to spend money are good at finding where to spend it. - ---- - -## Consequences for the rest of the site - -- **Nav loses "Pricing & support"** → `Features · How it works · Docs` + GitHub button. - Reflected in [homepage.md](homepage.md) §1. -- **Homepage loses the three-card paid block** from the first draft. Reflected in - [homepage.md](homepage.md). -- **`../pages/pricing.md`** (230 lines of Free/Starter/Pro/Business) is deleted, not - rewritten. -- **`../html/pricing.html`** (588 lines) is deleted. -- **`../pricing-strategy.md`** (431 lines) is obsolete on this site. It may still be - useful input to teem.cloud, so **move it rather than delete it** — it is the only place - the SMB segment analysis is written down, and it should not be lost to a `git rm`. -- **`../content-plan.md`** site structure loses `/pricing`; `/contact` should go too, on - the same logic — a contact form on the project site is a sales channel by another name. - GitHub issues is the contact channel for a project. -- **Anything in `../pages/*.md` promising a "free tier"** needs rewording. "Free tier" - implies a paid tier; the word for what we have is just *free*. - ---- - -## The one open judgement call - -Does the "Free. Forever." band belong on the homepage at all, or is it redundant? - -The hero already says open-source and self-hosted, and §3 already shows the Apache-2.0 -badge. An argument exists that a whole band restating it protests too much. - -**My recommendation: keep it, and keep it small.** Every visitor arriving from a -commercial CSPM is carrying the assumption that there is a catch, and one unambiguous -paragraph is cheaper than losing them to that suspicion. But it should read as a -statement of fact, not a sales counter-argument — no comparison table, no "unlike other -vendors", no exclamation marks. - -If it is cut, the `/pricing` redirect should point at the FAQ answer on the features -page instead of `#free`, so the URL still lands somewhere that answers the question. - ---- - -## Deleted from the current pricing page - -- Free / Starter ($149) / Pro ($449) / Business tiers — priced a SaaS we are not shipping -- "20% off annual" — no subscription product to discount -- Per-tier limits on AWS accounts, scan frequency, check count, history, users — none of - these limits exist in the software, and inventing them contradicts the licence -- "Not competing on price with DIY/open source" positioning — **we are the open source** -- The managed-hosting and support-services cards drafted earlier in this wireframe set — - those belong on teem.cloud, which is out of scope for `design/marketing/web/` diff --git a/docs/roadmap.md b/docs/roadmap.md index 5f9542b0..478b92da 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -100,6 +100,7 @@ Decisions already made, so we don't relitigate them. Each has a trigger for revi | **D-10** | **User documentation lives in a top-level `user-docs/` directory, not under `docs/`, and deploys to `docs.teemops.com`.** One site for technical and non-technical readers — no separate tracks. | 2026-07-31 | See below. | The content outgrows plain Markdown, or a contributor proposes a better home. | | **D-12** | **No security score.** Removed rather than recalibrated. Severity counts and the breakdown are what we show; a score can come back later if a design partner asks for one and we know what it should mean. | 2026-08-02 | See below. Closes [#91](https://github.com/teemops/tops/issues/91). | A design partner asks for a single headline number — and then design it so it can *move*. | | **D-11** | **A finding is a durable record keyed by AWS account + resource + rule, and findings are current state. No per-scan history, no observations table.** The most recent scan that examined a resource is authoritative for its content; status belongs to the user. | 2026-08-01 | See below. Shipped as [#81](https://github.com/teemops/tops/issues/81). | A design partner asks for trends over time — and then treat it as a new data model, not an addition to this one. | +| **D-14** | **`teemops.com` is a single page whose only job is recruiting design partners, not a product marketing site.** Built fresh in `www/`; the pre-pivot `design/marketing/web/` is deleted. | 2026-08-06 | See below. | Design partners exist and the constraint moves from recruitment to something else. | | **D-13** | **Docs renderer: MkDocs + Material theme**, deployed to `docs.teemops.com` via Cloudflare Pages (`mkdocs build`, output `site/`). Fills in the choice D-10 deliberately deferred. | 2026-08-03 | Clears the "MkDocs- or Docsify-class" bar D-10 set, now that section count and search actually bite (four pages against an eight-section, 34-page IA). Material gives sidebar nav, on-page TOC and client-side search for free — nothing here needed building by hand. Chosen over Docsify because it renders real static HTML per page rather than client-side, which matters for the evaluator audience D-10's own design work identified as arriving via search or a vendor-review link rather than already inside the app. Adds no new language to the repo: `python3` already backs the link-checker and SVG-validator scripts next to it in `user-docs/README.md`. | Content needs something outside MkDocs' plugin ecosystem, or the Python build step becomes a maintenance burden of its own. | > **Naming collision, flagged 2026-08-01.** [`durable-findings.md`](./features/durable-findings.md) @@ -109,6 +110,56 @@ Decisions already made, so we don't relitigate them. Each has a trigger for revi > renames it. **Worth renaming the story's ID to `DF-1`** — deferred rather than done > unilaterally, because it touches three docs and a settled wireframe. +### D-14 in full: what teemops.com is for + +**The milestone is limited by recruitment, not engineering** — this document has said so +since 2026-08-01 — and until 2026-08-06 there was no public page to send anyone to. +`teemops.com` served nothing. + +**What was there was worse than nothing.** `design/marketing/web/` held a complete, +well-built three-page site for a **hosted commercial SaaS**: Free/Starter/Pro/Business +pricing tiers, "Start Free" CTAs pointing at `app.teem.nz/register` — a domain that now +redirects to an unrelated property — and no mention anywhere that TOPS is open source. It +contradicted D-1 and D-6 on its face. It is deleted rather than kept as reference, because +a second, contradictory description of the product in the repo is a trap for whoever opens +it next. Git history has it. + +**The reframe that shaped the build.** A brand-new page with no traffic, no backlinks and no +search history will not generate inbound leads inside the milestone window. The realistic +sequence is outbound — a post, a message, an email — followed by the recipient looking us +up. So the page is a **conversion asset for outbound**, not a lead engine. That is why it is +one page and not eight: what it needs is a clear statement of what TOPS is, proof it is real +(the install one-liner, the GitHub repo, live docs, a version number), an honest account of +what it does *not* do, and one specific ask. Use-case pages, compliance landing pages and +SEO keyword targeting — all specified in the old content plan — are premature at zero +traffic and were dropped. + +**The "what it isn't" section is the load-bearing one.** It says AWS-only, not runtime +protection, not a compliance guarantee, no scheduled scans, no report export, PCI empty — +and that nobody outside the project is running it. For an audience of sceptical engineers, +volunteering the limits is what makes the rest of the page credible. It is also lifted +directly from `user-docs/start-here/what-tops-is.md`, so the two cannot drift into telling +different stories. + +**Every number on the page is checked against the code**, not against intent: 74 rules +(52 basic + 22 CIS), 11 services, all 74 carrying a remediation, all 28 critical/high +carrying step-by-step guidance. `www/README.md` records where each is verified, because +overstating any of them to a design partner costs more than it buys. + +**Lead capture is a Cloudflare Worker writing to D1**, protected by a honeypot field. +**Turnstile was built, tested and then removed before launch** — at five-partner volume a +few junk rows are cheaper to skim than a widget is to run, the endpoint sends no email and +publishes nothing so spam has no amplification path, and a third-party challenge script +that fails to load makes the form unsubmittable and loses a real lead silently. That last +risk is the one that decided it. Bot Fight Mode and a rate-limiting rule are the first two +responses if spam arrives; Turnstile is the third, and `www/README.md` records how. + +Deliberately no email notification either: reading leads is one command, and building +notification before a single lead exists is work with no evidence behind it. Deployment +reuses D-13's pattern — Workers static assets — so this adds no new category of +infrastructure, only a second project in the same account. **The result is that deploying +needs one CLI command and one dashboard step, with no secrets to manage at all.** + ### D-12 in full: why the security score is gone rather than fixed The score was `100 − (critical×10 + high×5 + medium×2 + low×1)`, floored at zero. @@ -324,14 +375,16 @@ reader gets what they need from the top of a page, a technical reader keeps scro **`docs.teemops.com`, not `.teem.nz`.** `teemops.com` is the domain already wired into the live app — `MAIL_FROM_ADDRESS` defaults to `help@teemops.com` (`app/config/mail.php:114`), and `docs/architecture.md:117` names `app.teemops.com`. -`teem.nz` only appears in `design/marketing/web/` — an unbuilt, pre-pivot marketing mockup -that still has a paid "Start Free" pricing page, which contradicts D-6. That directory is -stale and out of scope here; it's noted so the domain choice isn't relitigated by whoever -next opens it. +`teem.nz` only appeared in `design/marketing/web/` — an unbuilt, pre-pivot marketing mockup +that still had a paid "Start Free" pricing page, which contradicts D-6. **That directory was +deleted on 2026-08-06** when `www/` replaced it; see D-14. The note is kept so the domain +choice isn't relitigated by whoever next goes looking for it in git history. **Deployment: Cloudflare Pages**, connected to this repo, publishing `user-docs/`. This is -not a new category of infrastructure — `design/marketing/web/DEPLOY.md` already proposes -Cloudflare Pages for the marketing site; this applies the same plan to a second directory. +not a new category of infrastructure — the deleted marketing mockup's `DEPLOY.md` already +proposed Cloudflare Pages; this applies the same plan to a second directory. (In the event +D-13 landed on Cloudflare **Workers** static assets rather than Pages, and `www/` follows +it.) **Format: plain Markdown, tooling decided later.** Per the product practices — ship the smallest working version, don't reach for a framework before there's content to render — @@ -410,6 +463,7 @@ fixes are what made that run succeed, which is the sequencing argument justifyin | # | Feature | Why it's here | Size | | --- | --- | --- | :---: | +| **N-12** | **`teemops.com` — the design-partner recruitment page** | The milestone has been recruitment-limited since 2026-08-01 and there was nowhere to send anyone: `teemops.com` served nothing, and what was in the repo sold a hosted product with a pricing page. Built 2026-08-06 as one page in `www/`. See **D-14**. **Not yet deployed** — needs `npm run db:init` and the custom domain attached in the dashboard; no secrets. Steps in `www/README.md`. | S | | ~~**N-11**~~ | ~~Lock down the account-linking SNS topic~~ | ✅ **Done** 2026-08-03 — consumer-side validation ([#100](https://github.com/teemops/tops/issues/100)) and an install-scoped filter secret ([#101](https://github.com/teemops/tops/issues/101)), verified end to end on a real account: a correct install id links as before, a wrong one is filtered to quarantine and never reaches `teemops_main`. The live run also caught `aws:link-rejections` reporting "nothing rejected" while a message sat in quarantine — the silent failure moved one layer out, and is now fixed. [Feature doc](features/sns-topic-publish-authorization.md). | S + M | | ~~**N-1**~~ | ~~Fix the clean-checkout build~~ | ✅ **Done** 2026-07-29 — `@vitejs/plugin-vue` on `^6`, `npm ci` clean, frontend CI job added. | — | | ~~**N-2**~~ | ~~Choose and add a licence~~ | ✅ **Done** 2026-07-29 — Apache-2.0, trademark held separately, DCO for contributions. See D-7. | — | @@ -462,18 +516,14 @@ detail becomes a link into Findings, filtered. The per-finding list comes **off* #### Open — UI, in dependency order -**The P0/P1 run is complete.** #81, #82, #83, #85 and #86 have all landed; what remains is P2 -and below. **#88 (F-5, Insights by service) is the cheapest next thing** — S-1 built the -breakdown as a shared service and component precisely so Insights is a re-key rather than a -rewrite, and there is already a test proving the organization-wide path works. +**Nothing is left in this table. The UI workstream is closed** — verified against GitHub on +2026-08-06: #81, #82, #83, #85, #86, #87, #88, #89 and #91 are all closed. Every row that +used to sit here is in the Shipped table above. -| # | Item | Depends on | Size | Priority | -| --- | --- | --- | :---: | :---: | -| **#89** | F-6 · Insights by benchmark — **the last item in the milestone**; F-4 unblocked it | ✅ all met | XS | P3 | -| **#87** | F-4 · Filter Findings by compliance benchmark — the one genuine data-model change left; nothing records a finding's benchmark | #81 | M | P2 | -| **#88** | F-5 · Insights by service with severity breakdown | #86, #81 | S | P2 | -| **#91** | B-2 · Security score pinned at 0 and cannot improve | — | XS–S | P2 · bug | -| **#89** | F-6 · Insights by benchmark | #87, #88 | XS | P3 | +*The table that was here listed #87, #88, #89 and #91 as open for four days after they +landed, which is the failure mode this document is most prone to: the Shipped table gets +updated and the Open table does not. If you close something here, delete its row in the same +commit.* **One architectural instruction, worth repeating from the wireframes:** S-1's grouped, severity-stacked, drillable breakdown must be built as a **reusable component**. F-5 and F-6 @@ -534,11 +584,14 @@ Keep it to the P0/P1 items until a partner is actually watching. | # | Feature | Why it's here | Size | | --- | --- | --- | :---: | -| **X-1** | New-device email OTP | Wanted soon. Code prompt only on an unrecognised browser. Generator already exists — mostly extraction. | M | +| **X-10** | Trim the child IAM role to what TOPS actually uses | Fell out of N-11 and was never written down here. [#111](https://github.com/teemops/tops/issues/111) | S | +| **X-11** | `teemops_main` queue policy grants `SQS:ReceiveMessage` to `Principal: "*"` | Dead permission — the `aws:SourceArn` condition can never match a direct call — but it is a `Principal: "*"` in a public repo. Also from N-11. [#109](https://github.com/teemops/tops/issues/109) | XS | +| **X-1** | New-device email OTP | **Parked 2026-08-06, not dropped.** No design partner has asked, and the milestone is recruitment-limited; building the largest open item ahead of evidence is the anti-pattern this document names. Two findings from the discovery are worth keeping: the generator is welded to a Firebase ID token and keyed on `firebase_uid`, so it is a rewrite rather than the extraction this row claimed; and the default install cannot send email to a real inbox at all (see below). | M | | **X-3** | Prove the self-hosted path in CI | Nothing asserts the app boots with `FIREBASE_USER_AUTH=false` — the default config. | S | | **X-4** | Delete or route the dead OAuth controller | 99 lines, zero routes, unused dependency. Could give native-auth users OAuth without Firebase. | S | | **X-6** | Enforce DCO sign-off in CI | Sign-off is required in writing but unchecked. D-7's guarantee depends on provenance. **The repo is public, so an external PR can now arrive at any time.** | XS | | **X-5** | Reconcile member permissions | Code, comments and the plan doc disagree on who can manage members. | XS | +| **X-12** | A self-hoster cannot point TOPS at their own SMTP | `docker-compose.yml` hardcodes `MAIL_*` in `environment:`, which overrides `env_file:`. Verification and invitation email goes to a catcher on an unauthenticated port. Affects shipped features, not just X-1. | XS | | **X-8** | Publish a SHA256 for `install.sh` | N-3 documents the download-and-read form but cannot document a checksum, because the release workflow does not emit one. Small addition to `release.yml`. | XS | | **X-7** | Clear the remaining npm audit backlog | 17 → **5**, criticals at 0 and gated in CI. What's left needs a `firebase` major bump; nothing reaches a running instance. | XS | @@ -591,10 +644,10 @@ as a first slice plus continuous growth rather than a checklist. AWS account, run your first scan, what the IAM role can do, reading a finding, resolving a finding, the security model, reporting a vulnerability. Scan profiles and member management are priority-2, still ahead, per the IA's writing order -- [ ] Cloudflare Pages is connected and `docs.teemops.com` resolves to it — **D-13** picked - the renderer (MkDocs + Material) and the repo now builds; the Pages project itself - still needs connecting in the Cloudflare dashboard, which isn't something a repo - commit can do +- [x] `docs.teemops.com` resolves and serves the built site — confirmed live 2026-08-06. + **D-13** picked the renderer (MkDocs + Material); it deploys as Cloudflare **Workers** + static assets (`wrangler.jsonc` at the repo root) rather than Pages as originally + written - [ ] `README.md`'s setup section trims to a summary linking into `user-docs/`, so installation instructions have exactly one canonical copy @@ -660,10 +713,10 @@ Full research, the four options considered and why three were rejected, the open the proposed design, and acceptance criteria for both phases: **[docs/features/sns-topic-publish-authorization.md](features/sns-topic-publish-authorization.md)**. -- [ ] Phase 1 — consumer-side validation ships with tests — [#100](https://github.com/teemops/tops/issues/100) -- [ ] Phase 2 — install-scoped filter secret, verified end to end against a real AWS account — [#101](https://github.com/teemops/tops/issues/101) -- [ ] Payload filtering confirmed to work against a real CloudFormation message before it is relied on -- [ ] The architecture diagram's "unlimited child accounts" claim still holds after the change +- [x] Phase 1 — consumer-side validation ships with tests — [#100](https://github.com/teemops/tops/issues/100) +- [x] Phase 2 — install-scoped filter secret, verified end to end against a real AWS account — [#101](https://github.com/teemops/tops/issues/101) — **shipped and verified; the issue is still open on GitHub and wants closing** +- [x] Payload filtering confirmed to work against a real CloudFormation message before it is relied on — 2026-08-03 +- [x] The architecture diagram's "unlimited child accounts" claim still holds after the change --- @@ -1299,9 +1352,34 @@ the code worked fine — so only a test that reads what actually ships would hav Queued behind the design-partner milestone. Not started, not forgotten. -### X-1 · New-device email OTP +### X-1 · New-device email OTP — **parked 2026-08-06** -**User story** +**Why it is parked.** Picked up on 2026-08-06, taken through Discovery, and stopped before a +user story was written. Nobody has asked for it, the milestone is limited by recruiting +design partners rather than by shipping features, and it is the largest open item on the +board. The counter-argument — the repo is public, this is a security product, and +password-only access to a map of someone's AWS weaknesses is a poor look — is real, and is +why this is parked rather than moved to *Not Doing*. **D-5 still stands**: when it is built, +it is email OTP, not TOTP. + +**Two findings from the discovery, both worth keeping:** + +1. **This is a rewrite, not the extraction the summary below claims.** + `FirebaseAuthController::requestEmailOtp()` identifies the user by verifying a Firebase + **ID token** and caches under `mfa_email_otp:{firebase_uid}` — a column that is null for + every native-auth user. Both the input and the cache key have to be replaced. What is + genuinely reusable is about six lines plus `maskEmail()`; the valuable inheritance is the + *shape* (cache-backed, 6-digit, 10-minute expiry), not the code. It also uses `Mail::raw` + where the repo's pattern is a queued `Notification`. + +2. **The default install cannot send email to a real inbox, and `.env` cannot fix it.** See + **X-12** below. This is a prerequisite, and shipping OTP without it would deliver the + second factor to an unauthenticated mail catcher on the same host — the appearance of MFA + without the substance, which is worse than not shipping it. + +--- + +**User story** *(retained as written; not yet agreed)* > As a self-hosting user, I want to be asked for an emailed code only when I sign in from > a browser I haven't used before, so that a stolen password alone isn't enough to reach > my account — without adding friction to everyday logins. @@ -1330,6 +1408,32 @@ Queued behind the design-partner milestone. Not started, not forgotten. --- +### X-12 · A self-hoster cannot point TOPS at their own SMTP + +*Bug. Found 2026-08-06 during X-1's discovery, but it is not an MFA problem — it affects +mail that ships today.* + +`docker-compose.yml` sets `MAIL_MAILER`, `MAIL_HOST` and `MAIL_PORT` in the `environment:` +block, hardcoded to the bundled `maildev` catcher. The comment directly above them, added +for the queue settings, explains exactly why this is a bug: **`environment:` overrides +`env_file:`**, so a value in the operator's `.env` is ignored. Mail got the treatment the +queue settings were deliberately spared. + +The consequences exist now, without MFA: + +- **Email verification** (`MustVerifyEmail` is live) and **organisation invitations** both + send to a catcher, so an invited colleague never receives anything. Today the operator + has to know to open maildev's web UI on port `8090`. +- That UI is published on **all interfaces with no authentication** — fine for a local mail + catcher, not fine as the place account email lands. +- Changing it means editing `docker-compose.yml`, a file `install.sh` owns and an upgrade + may replace. + +**The fix is XS**: move the three `MAIL_*` keys out of `environment:` so `.env` layering +wins, keep `maildev` as the default for anyone who has configured nothing, and document the +real-SMTP variables in `.env.example`. **Blocks X-1**, and should be done regardless of +whether X-1 is ever built. + ### X-3 · Prove the self-hosted path in CI No test asserts the app boots and authenticates with `FIREBASE_USER_AUTH=false` — which @@ -1450,6 +1554,25 @@ Blocking nothing today, but each one shapes the plan: ## Changelog +- **2026-08-06** — **The plan turned from shipping to recruiting, and this document caught + up with itself.** X-1 (email OTP) was picked up, taken through Discovery and **parked** + before a user story existed: nobody has asked for it, and it is the largest open item on a + board whose stated constraint is finding five operators. Its discovery is kept, because it + found two things worth more than the feature would have been — the "generator already + exists, mostly extraction" claim is wrong (it is keyed on a Firebase ID token and + `firebase_uid`, so it is a rewrite), and **the default install cannot send email to a real + inbox at all**, now filed as **X-12**. That second one is a live bug affecting email + verification and organisation invitations today, not a hypothetical MFA prerequisite. + In its place, **N-12**: `teemops.com` built as a single design-partner recruitment page + (**D-14**), with the pre-pivot `design/marketing/web/` mockup deleted — it sold a hosted + product with Free/Starter/Pro/Business pricing and CTAs pointing at a domain that now + redirects elsewhere, contradicting D-1 and D-6 on its face. **A review of this document + against GitHub also found it stale in four places**, all now corrected: N-11's checkboxes + were unticked though it shipped on 2026-08-03; the workstream's "Open — UI" table still + listed #87, #88, #89 and #91 four days after they closed; `docs.teemops.com` was recorded + as not yet connected when it has been live and serving; and [#109](https://github.com/teemops/tops/issues/109) + and [#111](https://github.com/teemops/tops/issues/111), both filed on 2026-08-03 out of + N-11, appeared nowhere at all — now **X-11** and **X-10**. - **2026-08-02** — **S-1 landed, and the P0/P1 run of this workstream is complete.** Scan detail summarises and dispatches: run facts, severity totals, "fix these first" ranked by severity weight rather than raw count, and a drillable breakdown whose every row links into diff --git a/www/.gitignore b/www/.gitignore new file mode 100644 index 00000000..5620f5ea --- /dev/null +++ b/www/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.wrangler/ + +# Generated by `wrangler types` (npm run typecheck regenerates it). +# 14k lines of derived declarations do not belong in review diffs. +worker-configuration.d.ts diff --git a/www/README.md b/www/README.md new file mode 100644 index 00000000..f8c9d25a --- /dev/null +++ b/www/README.md @@ -0,0 +1,164 @@ +# teemops.com + +The marketing site and its design-partner signup form. One page, deployed to Cloudflare +Workers as static assets plus a single API route. + +**This is a separate Workers project from the docs site.** The repo root's +`wrangler.jsonc` is `docs.teemops.com` (built by `mkdocs.yml`); this directory's is +`teemops.com`. Run every command below from inside `www/`, or you will deploy the wrong +one. + +## What's here + +``` +www/ +├── wrangler.jsonc # Worker config — assets, D1 binding, observability +├── schema.sql # the design_partner_leads table +├── vitest.config.ts # runs the tests inside workerd, against a real local D1 +├── build-assets.py # regenerates public/og.png and public/favicon.ico +├── src/ +│ └── index.ts # POST /api/design-partner — the only server-side code +├── test/ +│ └── signup.test.ts # 16 tests over that endpoint +└── public/ # everything else is static + ├── index.html # the page, with its CSS and JS inline + ├── 404.html + ├── og.png # generated — do not edit by hand + ├── favicon.ico # generated — do not edit by hand + ├── logo.png # the source both are derived from + ├── robots.txt + └── sitemap.xml +``` + +## First-time setup + +Two CLI commands and one dashboard step. There are no secrets to set. + +### 1. Create the leads table + +The D1 database `tops-www-leads` already exists. Create its schema in the remote copy: + +```bash +npm run db:init +``` + +### 2. Deploy + +```bash +npm run deploy +``` + +### 3. Point teemops.com at it + +In **Workers & Pages → tops-www → Settings → Domains & Routes**, add `teemops.com` and +`www.teemops.com` as custom domains. This is dashboard-only — a repo commit cannot do it. + +## Reading the leads + +```bash +npm run leads +``` + +That prints every signup, newest first. For the message someone left as well: + +```bash +npx wrangler d1 execute tops-www-leads --remote \ + --command="SELECT created_at, name, email, company, aws_scale, notes FROM design_partner_leads ORDER BY created_at DESC LIMIT 20" +``` + +**Nothing emails you when a lead arrives.** You have to run this. That is a deliberate +starting point rather than an oversight — it is one command, and adding notification +before there is a single lead to notify about is work with no evidence behind it. When +checking manually gets annoying, that is the signal to add it, and the account already has +`email_sending` available for exactly that. + +## Spam protection, and what to do if it stops working + +The form is protected by a **honeypot**: a hidden `website` field that people never see and +bots tend to fill. If it arrives non-empty the submission is dropped and the endpoint +answers `201` anyway, so a bot gets no signal about which field gave it away. The name is +defined once in `src/index.ts` as `HONEYPOT_FIELD` and must match the input in +`public/index.html`. + +**There is deliberately no CAPTCHA.** Turnstile was built and then removed before launch, +for three reasons: at five-design-partner volume a handful of junk rows is easier to skim +past than a widget is to maintain; the endpoint sends no email and publishes nothing, so +spam has no amplification path; and a third-party challenge script that fails to load — +corporate network, privacy extension — makes the form unsubmittable and loses a real lead +with no signal that it happened. + +**If you start getting spam**, in increasing order of effort: + +1. Turn on **Bot Fight Mode** for the zone. No code, no deploy. +2. Add a **rate-limiting rule** on `/api/design-partner`. Still no code. +3. Add [Turnstile](https://developers.cloudflare.com/turnstile/) — a widget in the + dashboard, its site key in the page, `wrangler secret put TURNSTILE_SECRET_KEY`, and a + `siteverify` call in `handleSignup`. Note the stored OAuth token lacks + `challenge-widgets.write`, so creating the widget from the CLI needs `wrangler login` + first. If you do this, never ship Cloudflare's test key (`1x00000000000000000000AA`) — + it always passes, so the form would look protected and be wide open. + +Reach for 3 only if 1 and 2 have not held. + +## Tests + +```bash +npm test +``` + +16 tests covering `POST /api/design-partner`, run inside `workerd` against a real local D1 +via `@cloudflare/vitest-pool-workers` — so the SQL is genuinely executed rather than +mocked. They cover the happy path, field trimming and length caps, every validation +rejection, the honeypot (including that a trapped request is byte-for-byte +indistinguishable from a genuine one), and the method and path guards. + +Each assertion checks the database as well as the status code, because the failure that +matters is a submission that answers `201` and stores nothing. + +Note `@cloudflare/vitest-pool-workers` 0.20 removed the `/config` subpath and the +`defineWorkersConfig` helper that most examples online still use. On vitest 4 the pool +options go to a `cloudflareTest()` **plugin** — see the comment in `vitest.config.ts`. + +## Local development + +```bash +npm install +npm run db:init:local +npm run dev +``` + +Then open the printed URL. There are no secrets and no `.dev.vars` to set up. + +Inspect what local submissions wrote: + +```bash +npx wrangler d1 execute tops-www-leads --local --command="SELECT * FROM design_partner_leads" +``` + +## Changing the page + +The CSS and JS are inline in `public/index.html` on purpose — the page is one file, has no +build step, and loads no third-party assets at all. Keep it that way +unless there is a reason not to. + +After changing the headline, regenerate the derived assets so the link-preview card and +the page agree: + +```bash +python3 build-assets.py +``` + +## Claims made on this page + +The page states specific numbers. They were true at v0.5.0 and they are checkable — if you +change the rules, check them again: + +| Claim | Source | +| --- | --- | +| 74 checks | `app/rules/rulesets/basic.json` (52) + `cis.json` (22) | +| 11 AWS services | directories under `app/rules/tasks/` | +| 28 with step-by-step guidance | `app/rules/recommendations/tips.json` | +| Install needs only Docker | `install.sh`, and D-8 in `docs/roadmap.md` | + +Overstating any of these to a design partner costs more than it buys — they will install it +and find out. diff --git a/www/build-assets.py b/www/build-assets.py new file mode 100644 index 00000000..691f0d63 --- /dev/null +++ b/www/build-assets.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Generate the two derived brand assets in public/. + +- og.png the 1200x630 card shown when teemops.com is shared. Link previews + are the first thing most visitors see, because the site is reached + from a message someone sent them rather than from search. +- favicon.ico browsers request /favicon.ico whether or not a + points elsewhere, so without this every visit logs a 404. + +Run after changing the headline or the logo: + + python3 www/build-assets.py +""" +from pathlib import Path + +from PIL import Image, ImageDraw, ImageFont + +HERE = Path(__file__).parent +OUT = HERE / "public" / "og.png" +FAVICON = HERE / "public" / "favicon.ico" +LOGO = HERE / "public" / "logo.png" + +W, H = 1200, 630 +BG = (10, 14, 23) +TEXT = (233, 237, 245) +MUTED = (152, 163, 184) +BRAND = (245, 130, 31) + +FONT_CANDIDATES = { + "bold": [ + "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", + "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf", + ], + "regular": [ + "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", + "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", + ], + "mono": [ + "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", + "/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", + ], +} + + +def font(kind: str, size: int) -> ImageFont.FreeTypeFont: + for path in FONT_CANDIDATES[kind]: + if Path(path).exists(): + return ImageFont.truetype(path, size) + return ImageFont.load_default(size) + + +def glow(img: Image.Image) -> None: + """A soft brand-coloured wash in the top-left, echoing the page hero.""" + overlay = Image.new("RGBA", (W, H), (0, 0, 0, 0)) + draw = ImageDraw.Draw(overlay) + cx, cy, radius = 120, -40, 620 + steps = 60 + for i in range(steps, 0, -1): + r = radius * i / steps + alpha = int(30 * (1 - i / steps) ** 1.6) + draw.ellipse((cx - r, cy - r * 0.72, cx + r, cy + r * 0.72), fill=(*BRAND, alpha)) + img.alpha_composite(overlay) + + +def main() -> None: + img = Image.new("RGBA", (W, H), (*BG, 255)) + glow(img) + draw = ImageDraw.Draw(img) + + margin = 84 + y = 96 + + if LOGO.exists(): + logo = Image.open(LOGO).convert("RGBA") + logo.thumbnail((78, 78), Image.LANCZOS) + img.alpha_composite(logo, (margin, y - 8)) + draw.text((margin + 96, y + 12), "Teemops", font=font("bold", 42), fill=TEXT) + + y += 132 + for line in ("Open source AWS security", "scanning you run yourself"): + draw.text((margin, y), line, font=font("bold", 62), fill=TEXT) + y += 76 + + y += 26 + for line in ( + "Overly permissive IAM roles, public S3 buckets, open", + "security groups. 74 checks, each with the fix.", + ): + draw.text((margin, y), line, font=font("regular", 30), fill=MUTED) + y += 42 + + # Footer rule and badge row. + draw.line((margin, H - 106, W - margin, H - 106), fill=(255, 255, 255, 28), width=1) + draw.text( + (margin, H - 76), + "Apache 2.0 · Self-hosted · No paid tier", + font=font("mono", 25), + fill=BRAND, + ) + draw.text( + (W - margin - 190, H - 76), "teemops.com", font=font("mono", 25), fill=MUTED + ) + + img.convert("RGB").save(OUT, "PNG", optimize=True) + print(f"wrote {OUT} ({OUT.stat().st_size // 1024} KB)") + + +def favicon() -> None: + """Multi-size .ico from the logo. Keeps the transparent background so the + mark sits on whatever colour the browser's tab strip happens to be.""" + if not LOGO.exists(): + print(f"skipped {FAVICON} — {LOGO} is missing") + return + src = Image.open(LOGO).convert("RGBA") + src.save(FAVICON, format="ICO", sizes=[(16, 16), (32, 32), (48, 48)]) + print(f"wrote {FAVICON} ({FAVICON.stat().st_size // 1024} KB)") + + +if __name__ == "__main__": + main() + favicon() diff --git a/www/package-lock.json b/www/package-lock.json new file mode 100644 index 00000000..5365833f --- /dev/null +++ b/www/package-lock.json @@ -0,0 +1,2804 @@ +{ + "name": "tops-www", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tops-www", + "devDependencies": { + "@cloudflare/vitest-pool-workers": "^0.20.3", + "@types/node": "^24.3.0", + "typescript": "^5.9.2", + "vitest": "^4.1.10", + "wrangler": "^4.119.0" + } + }, + "node_modules/@cloudflare/kv-asset-handler": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz", + "integrity": "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==", + "dev": true, + "license": "MIT OR Apache-2.0", + "peerDependencies": { + "unenv": "2.0.0-rc.24", + "workerd": ">1.20260305.0 <2.0.0-0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } + } + }, + "node_modules/@cloudflare/vitest-pool-workers": { + "version": "0.20.3", + "resolved": "https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.20.3.tgz", + "integrity": "sha512-aCMvM5zQ3MTz8SorSZB6ZxjVK2Gof6UhIc2Z1z9zbX/obucSYwDUkx8A0MUOod4I7clfB0QLarKBjRdIczK3vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cjs-module-lexer": "1.2.3", + "esbuild": "0.28.1", + "miniflare": "5.20260801.1-alpha", + "wrangler": "4.120.0", + "zod": "4.4.3" + }, + "peerDependencies": { + "@vitest/runner": "^4.1.0", + "@vitest/snapshot": "^4.1.0", + "vitest": "^4.1.0" + } + }, + "node_modules/@cloudflare/workerd-darwin-64": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260801.1.tgz", + "integrity": "sha512-wuJWbXpKvncJi1P0GKS+iYpN5tHdb7JPJJ/+6ZQe8zzovHHVMkLJPNBsgWpqeUhpM3g9qTwEKd2rglNKejuh5A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-darwin-arm64": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260801.1.tgz", + "integrity": "sha512-kwoZiTpnhNrF3+APx84Q/oAqvJ3sU9yefGagwm/ASaH/2W19x0vghkW/r4qCoHCK0WW7EPugZ+aXjgPMRtlq1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-64": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260801.1.tgz", + "integrity": "sha512-r0vAxCZH+Jih9Unm1yoyiByPNWNgawcKciOHDm5Q37ZVGOkKLsT9AtLe3yLSaul76WrKqtf+JP2n0WW32VBLJg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-linux-arm64": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260801.1.tgz", + "integrity": "sha512-zWgpdZtSozvIgzQNmQiDSF8yEOQJUkRAWNsDXXzAAoy+fCn8YUoSibj3mpFSbZRvbUldeBEaW6SCdC2VEMkhNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cloudflare/workerd-windows-64": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260801.1.tgz", + "integrity": "sha512-2oQz+Ksu4ji6e/+ZoYX+tWQEcxAii2p7l+iR8kx48W1llMalaufAsmVxTlk+3/vrM7D3/2c0iK448e0UQTcIMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.2.tgz", + "integrity": "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.1" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.2.tgz", + "integrity": "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.1" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.2.tgz", + "integrity": "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.2" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.1.tgz", + "integrity": "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.1.tgz", + "integrity": "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.1.tgz", + "integrity": "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.1.tgz", + "integrity": "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.1.tgz", + "integrity": "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.1.tgz", + "integrity": "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.1.tgz", + "integrity": "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.1.tgz", + "integrity": "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.1.tgz", + "integrity": "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.1.tgz", + "integrity": "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.2.tgz", + "integrity": "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.1" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.2.tgz", + "integrity": "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.1" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.2.tgz", + "integrity": "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.1" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.2.tgz", + "integrity": "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.1" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.2.tgz", + "integrity": "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.1" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.2.tgz", + "integrity": "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.1" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.2.tgz", + "integrity": "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.2.tgz", + "integrity": "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.1" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.2.tgz", + "integrity": "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw==", + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.2.tgz", + "integrity": "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.2" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.2.tgz", + "integrity": "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.2.tgz", + "integrity": "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.2.tgz", + "integrity": "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.23", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.23.tgz", + "integrity": "sha512-iRoq6i6JDJP6Mt2A5JaPvzw0pgYHH6k92ij+yXiTrB7T2y9N789aWE3EHWj/5ztlJBokcCBja3iYLVdu5wgnkg==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", + "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", + "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.10", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", + "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", + "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.10", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", + "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "@vitest/utils": "4.1.10", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", + "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", + "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.10", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", + "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/miniflare": { + "version": "5.20260801.1-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260801.1-alpha.tgz", + "integrity": "sha512-BHPVzIDA6mbx7LefxpvkXW7DHx9FKB9GorZatbnrrFTt3CVMU8zuUpbgyCuebwDKcTTOZos43ta8GQ0eMVEpxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "0.8.1", + "sharp": "0.35.2", + "undici": "7.29.0", + "workerd": "1.20260801.1", + "ws": "8.21.0", + "youch": "4.1.0-beta.10" + }, + "engines": { + "node": ">=22.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/path-to-regexp": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rolldown": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.143.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp": { + "version": "0.35.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.2.tgz", + "integrity": "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.2", + "@img/sharp-darwin-x64": "0.35.2", + "@img/sharp-freebsd-wasm32": "0.35.2", + "@img/sharp-libvips-darwin-arm64": "1.3.1", + "@img/sharp-libvips-darwin-x64": "1.3.1", + "@img/sharp-libvips-linux-arm": "1.3.1", + "@img/sharp-libvips-linux-arm64": "1.3.1", + "@img/sharp-libvips-linux-ppc64": "1.3.1", + "@img/sharp-libvips-linux-riscv64": "1.3.1", + "@img/sharp-libvips-linux-s390x": "1.3.1", + "@img/sharp-libvips-linux-x64": "1.3.1", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", + "@img/sharp-libvips-linuxmusl-x64": "1.3.1", + "@img/sharp-linux-arm": "0.35.2", + "@img/sharp-linux-arm64": "0.35.2", + "@img/sharp-linux-ppc64": "0.35.2", + "@img/sharp-linux-riscv64": "0.35.2", + "@img/sharp-linux-s390x": "0.35.2", + "@img/sharp-linux-x64": "0.35.2", + "@img/sharp-linuxmusl-arm64": "0.35.2", + "@img/sharp-linuxmusl-x64": "0.35.2", + "@img/sharp-webcontainers-wasm32": "0.35.2", + "@img/sharp-win32-arm64": "0.35.2", + "@img/sharp-win32-ia32": "0.35.2", + "@img/sharp-win32-x64": "0.35.2" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3" + } + }, + "node_modules/vite": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", + "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.10", + "@vitest/mocker": "4.1.10", + "@vitest/pretty-format": "4.1.10", + "@vitest/runner": "4.1.10", + "@vitest/snapshot": "4.1.10", + "@vitest/spy": "4.1.10", + "@vitest/utils": "4.1.10", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.10", + "@vitest/browser-preview": "4.1.10", + "@vitest/browser-webdriverio": "4.1.10", + "@vitest/coverage-istanbul": "4.1.10", + "@vitest/coverage-v8": "4.1.10", + "@vitest/ui": "4.1.10", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/workerd": { + "version": "1.20260801.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260801.1.tgz", + "integrity": "sha512-/g9JGTyqnHtoIscpBHqKD8swE2V4StBs2i69PmLiOhH45OP95jCFICl4F1hKlgN57rqfni5LiCitttoX5OOkVA==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "bin": { + "workerd": "bin/workerd" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@cloudflare/workerd-darwin-64": "1.20260801.1", + "@cloudflare/workerd-darwin-arm64": "1.20260801.1", + "@cloudflare/workerd-linux-64": "1.20260801.1", + "@cloudflare/workerd-linux-arm64": "1.20260801.1", + "@cloudflare/workerd-windows-64": "1.20260801.1" + } + }, + "node_modules/wrangler": { + "version": "4.120.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.120.0.tgz", + "integrity": "sha512-cBmu/MeaB/fPacC0JpATs4duTOCagBxrZo+vBzuTX06tLzwSyAHE1drlHUZ8rP0VqVz1fy3ReGYTiHdKkoHltg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@cloudflare/kv-asset-handler": "0.5.0", + "@cloudflare/unenv-preset": "2.16.1", + "blake3-wasm": "2.1.5", + "esbuild": "0.28.1", + "miniflare": "5.20260801.1-alpha", + "path-to-regexp": "6.3.0", + "unenv": "2.0.0-rc.24", + "workerd": "1.20260801.1" + }, + "bin": { + "cf-wrangler": "bin/cf-wrangler.js", + "wrangler": "bin/wrangler.js", + "wrangler2": "bin/wrangler.js" + }, + "engines": { + "node": ">=22.0.0" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + }, + "peerDependencies": { + "@cloudflare/workers-types": "^5.20260801.1" + }, + "peerDependenciesMeta": { + "@cloudflare/workers-types": { + "optional": true + } + } + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/youch": { + "version": "4.1.0-beta.10", + "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", + "integrity": "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@poppinss/dumper": "^0.6.4", + "@speed-highlight/core": "^1.2.7", + "cookie": "^1.0.2", + "youch-core": "^0.3.3" + } + }, + "node_modules/youch-core": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz", + "integrity": "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/exception": "^1.2.2", + "error-stack-parser-es": "^1.0.5" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/www/package.json b/www/package.json new file mode 100644 index 00000000..05ad7782 --- /dev/null +++ b/www/package.json @@ -0,0 +1,28 @@ +{ + "name": "tops-www", + "private": true, + "type": "module", + "description": "teemops.com — marketing site and design-partner signup", + "scripts": { + "dev": "wrangler dev", + "deploy": "wrangler deploy", + "typecheck": "wrangler types && tsc --noEmit", + "types": "wrangler types", + "db:init": "wrangler d1 execute tops-www-leads --remote --file=./schema.sql", + "db:init:local": "wrangler d1 execute tops-www-leads --local --file=./schema.sql", + "leads": "wrangler d1 execute tops-www-leads --remote --command=\"SELECT id, created_at, name, email, company, aws_scale FROM design_partner_leads ORDER BY created_at DESC\"", + "test": "vitest run", + "test:watch": "vitest" + }, + "devDependencies": { + "@cloudflare/vitest-pool-workers": "^0.20.3", + "@types/node": "^24.3.0", + "typescript": "^5.9.2", + "vitest": "^4.1.10", + "wrangler": "^4.119.0" + }, + "allowScripts": { + "esbuild@0.28.1": true, + "workerd@1.20260801.1": true + } +} diff --git a/www/public/404.html b/www/public/404.html new file mode 100644 index 00000000..53997556 --- /dev/null +++ b/www/public/404.html @@ -0,0 +1,30 @@ + + + + + +Not found — Teemops + + + + +
+

404

+

There's nothing here.

+

This site is one page, so that was probably a stale link.

+

Go to teemops.com · Read the docs

+
+ + diff --git a/www/public/favicon.ico b/www/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..7ed43878e54dbf851137d9763316f73f87e44848 GIT binary patch literal 3485 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 + + + + +Teemops — open source AWS security scanning you run yourself + + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+ Apache-2.0 + Self-hosted + No paid tier +
+

Open source AWS security scanning you run yourself

+

+ Teemops finds IAM users with AdministratorAccess, S3 buckets missing + public access block, security groups open to 0.0.0.0/0 on port 22, and + unencrypted RDS instances. 74 checks across 11 AWS services, each with the + steps to fix it. It runs in your infrastructure, so findings stay in your + account. +

+ + + +
+
+ + install — requires Docker +
+
+
$ bash <(curl -fsSL https://raw.githubusercontent.com/teemops/tops/develop/install.sh)
+ +
+
+

+ The installer pulls tagged images from Docker Hub, so the host needs no PHP, Node or + Composer. To read the script before running it, the + install guide shows the + download-and-inspect form. +

+
+
+ + +
+
+
+

What it does

+

Every finding comes with the fix

+

+ A list of problems without remediation steps just moves the work to you. +

+
+ +
+
+

74 checks across 11 services

+

S3, IAM, EC2, RDS, CloudTrail, KMS, Lambda, DynamoDB, ELBv2, SNS and SQS. Run the + general baseline, the CIS AWS Foundations Benchmark, or both. You can also scan a + single service.

+
+
+

Remediation on every check

+

All 74 checks include a fix. The 28 critical and high severity checks include + step-by-step guidance with links to the AWS documentation.

+
+
+

No stored AWS credentials

+

Teemops assumes a cross-account IAM role that your administrators create with + CloudFormation and can revoke at any time. No access keys are stored.

+
+
+

Self-hosted

+

It runs on your infrastructure against your own database. There is no hosted + service, no telemetry and no account to create.

+
+
+

Findings persist across scans

+

A finding is one record per account, resource and rule. Mark one ignored and it + stays ignored on the next scan rather than reappearing.

+
+
+

Apache 2.0, with a DCO

+

Contributions use a DCO rather than a CLA, so the licence cannot change later + without every contributor agreeing. No paid tier, no features behind a licence.

+
+
+
+
+ + +
+
+
+

How it works

+

From install to first scan

+
+
+
+ 01 +

Install

+

One command on a host with Docker. The installer generates its own database + credentials and pulls tagged images. There is no build step.

+
+
+ 02 +

Connect an account

+

A CloudFormation stack creates the cross-account IAM role in the account you want + to scan. You can read the template before you launch it.

+
+
+ 03 +

Scan

+

Run the full benchmark or narrow it to specific services. Findings are grouped by + severity, each with its remediation.

+
+
+
+
+ + +
+
+
+

What it isn't

+

What Teemops does not do

+

+ Teemops is at v0.5.0. Here are the limits, so you can decide before you install it + rather than after. +

+
+ +
+
    +
  • Not runtime protection It reads configuration through the AWS + API. It does not inspect traffic, block requests or sit in the request path.
  • +
+
    +
  • AWS only Azure and GCP are on the roadmap, not in the code.
  • +
+
    +
  • Not a compliance guarantee A clean scan means the checks + Teemops runs found nothing. It is not an audit. The PCI profile has no rules + written yet, so it is hidden rather than shown empty.
  • +
+
    +
  • No automated remediation Teemops reports the problem and the + fix. You apply the change in your own account.
  • +
+
    +
  • No scheduled scans or report export Scans are run manually. + Both features are on the roadmap; neither has a route or a UI today.
  • +
+
    +
  • Not yet running outside the project Teemops has scanned real + AWS accounts, but no external team runs it today. That is what design partners + are for.
  • +
+
+ +

+ The full list, checked against the code rather than against intent, is in + PROGRESS.md. +

+
+
+ + +
+
+
+
+

The ask

+

We're looking for five design partners

+

+ Teemops works. It has scanned real AWS accounts and found real problems. What it + has not done is run in an environment we did not build. Until it does, decisions + about what to build next are guesses. +

+ +

What you get

+
    +
  • Direct contact with the maintainer, by email. Not a support + queue.
  • +
  • Issues you hit go to the top of the roadmap. That is the + point of the arrangement.
  • +
  • Influence over the roadmap. Scheduled scans, report export + and wider service coverage are all waiting on someone to say which matters + most.
  • +
  • Apache 2.0 with a DCO. There is no pricing tier waiting to + appear.
  • +
+ +

What we ask

+
    +
  • Install it from the documentation and tell us where the + documentation is wrong.
  • +
  • Scan a real AWS account, not a clean test account.
  • +
  • Thirty minutes to tell us what was confusing or missing.
  • +
+

+ No cost and no contract. If you install it and decide it is not useful, telling us + why is still worth your thirty minutes. +

+
+ +
+
+

Sign up as a design partner

+

+ We reply personally, usually within a day or two. +

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + + + + + +
+ +

+ We store your name, email and message. Nothing else, and only to reply. You can + also email help@teemops.com. +

+
+
+
+
+
+
+ + + + + + diff --git a/www/public/logo.png b/www/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bcb45eee4a39f15bedcb3eecf02e94752a9ae8a0 GIT binary patch literal 41486 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 literal 0 HcmV?d00001 diff --git a/www/public/robots.txt b/www/public/robots.txt new file mode 100644 index 00000000..7223e6d9 --- /dev/null +++ b/www/public/robots.txt @@ -0,0 +1,5 @@ +User-agent: * +Allow: / +Disallow: /api/ + +Sitemap: https://teemops.com/sitemap.xml diff --git a/www/public/sitemap.xml b/www/public/sitemap.xml new file mode 100644 index 00000000..d7443d56 --- /dev/null +++ b/www/public/sitemap.xml @@ -0,0 +1,8 @@ + + + + https://teemops.com/ + weekly + 1.0 + + diff --git a/www/src/index.ts b/www/src/index.ts new file mode 100644 index 00000000..6abac86c --- /dev/null +++ b/www/src/index.ts @@ -0,0 +1,137 @@ +/** + * teemops.com — static pages plus one endpoint. + * + * Static files in public/ are served by the assets binding before this Worker + * runs, so the only thing here is the design-partner signup handler. + */ + +const MAX_BODY_BYTES = 8 * 1024; + +const LIMITS = { + name: 100, + email: 254, // RFC 5321 maximum + company: 100, + aws_scale: 20, + notes: 2000, +} as const; + +const AWS_SCALES = new Set(['1', '2-5', '6-20', '20+', '']); + +/** Must match the hidden input's name in public/index.html. */ +const HONEYPOT_FIELD = 'website'; + +interface LeadSubmission { + name: string; + email: string; + company: string; + aws_scale: string; + notes: string; +} + +function json(body: unknown, status: number): Response { + return new Response(JSON.stringify(body), { + status, + headers: { 'content-type': 'application/json; charset=utf-8' }, + }); +} + +/** + * Email validation is deliberately loose. The only thing that matters is that a + * reply can be sent, and the authoritative test of that is sending one — a + * strict pattern here would reject valid addresses and cost real leads. + */ +function looksLikeEmail(value: string): boolean { + return /^[^\s@]+@[^\s@.]+\.[^\s@]+$/.test(value); +} + +function readField(form: FormData, key: string, limit: number): string { + const raw = form.get(key); + return typeof raw === 'string' ? raw.trim().slice(0, limit) : ''; +} + +function parseSubmission(form: FormData): { lead: LeadSubmission } | { error: string } { + const lead: LeadSubmission = { + name: readField(form, 'name', LIMITS.name), + email: readField(form, 'email', LIMITS.email), + company: readField(form, 'company', LIMITS.company), + aws_scale: readField(form, 'aws_scale', LIMITS.aws_scale), + notes: readField(form, 'notes', LIMITS.notes), + }; + + if (!lead.name) return { error: 'Please tell us your name.' }; + if (!looksLikeEmail(lead.email)) return { error: 'That email address does not look right.' }; + if (!AWS_SCALES.has(lead.aws_scale)) return { error: 'Please pick one of the listed options.' }; + + return { lead }; +} + +async function handleSignup(request: Request, env: Env): Promise { + const contentLength = Number(request.headers.get('content-length') ?? '0'); + if (contentLength > MAX_BODY_BYTES) { + return json({ error: 'That message is too long.' }, 413); + } + + let form: FormData; + try { + form = await request.formData(); + } catch { + return json({ error: 'We could not read that submission.' }, 400); + } + + // Honeypot. The field is hidden from people and left empty by them; bots that + // fill every input give themselves away. Answer 201 rather than an error, so a + // bot gets no signal telling it which field to skip next time. + if (readField(form, HONEYPOT_FIELD, 200) !== '') { + console.warn(JSON.stringify({ event: 'lead_rejected_honeypot' })); + return json({ ok: true }, 201); + } + + const parsed = parseSubmission(form); + if ('error' in parsed) { + return json({ error: parsed.error }, 422); + } + + const { lead } = parsed; + + try { + await env.LEADS_DB.prepare( + `INSERT INTO design_partner_leads (name, email, company, aws_scale, notes) + VALUES (?, ?, ?, ?, ?)` + ) + .bind(lead.name, lead.email, lead.company, lead.aws_scale, lead.notes) + .run(); + } catch (error) { + // Never surface the database error to the visitor, but do not pretend it + // worked either — a lead that silently vanishes is the one failure this + // endpoint exists to prevent. + console.error( + JSON.stringify({ + event: 'lead_insert_failed', + message: error instanceof Error ? error.message : String(error), + }) + ); + return json( + { error: 'Something broke on our end. Please email help@teemops.com instead.' }, + 500 + ); + } + + console.log(JSON.stringify({ event: 'lead_captured', scale: lead.aws_scale || 'unstated' })); + + return json({ ok: true }, 201); +} + +export default { + async fetch(request: Request, env: Env): Promise { + const url = new URL(request.url); + + if (url.pathname === '/api/design-partner') { + if (request.method !== 'POST') { + return json({ error: 'Method not allowed.' }, 405); + } + return handleSignup(request, env); + } + + return new Response('Not found', { status: 404 }); + }, +} satisfies ExportedHandler; diff --git a/www/test/signup.test.ts b/www/test/signup.test.ts new file mode 100644 index 00000000..698c2c32 --- /dev/null +++ b/www/test/signup.test.ts @@ -0,0 +1,153 @@ +import { env, createExecutionContext, waitOnExecutionContext } from 'cloudflare:test'; +import { beforeEach, describe, expect, it } from 'vitest'; + +import worker from '../src/index'; + +const ENDPOINT = 'https://teemops.com/api/design-partner'; + +/** Mirrors schema.sql. Applied per test file because D1 starts empty here. */ +const SCHEMA = ` +CREATE TABLE IF NOT EXISTS design_partner_leads ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT NOT NULL, + company TEXT, + aws_scale TEXT, + notes TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')) +);`; + +async function post(fields: Record, method = 'POST'): Promise { + const body = new FormData(); + for (const [k, v] of Object.entries(fields)) body.append(k, v); + + const request = new Request(ENDPOINT, { + method, + body: method === 'POST' ? body : undefined, + }); + const ctx = createExecutionContext(); + const response = await worker.fetch(request, env, ctx); + await waitOnExecutionContext(ctx); + return response; +} + +async function leadCount(): Promise { + const row = await env.LEADS_DB.prepare( + 'SELECT count(*) AS n FROM design_partner_leads' + ).first<{ n: number }>(); + return row?.n ?? 0; +} + +const VALID = { + name: 'Grace Hopper', + email: 'grace@example.com', + company: 'Navy', + aws_scale: '2-5', + notes: 'Worried about IAM sprawl.', +}; + +beforeEach(async () => { + await env.LEADS_DB.exec(SCHEMA.replace(/\n/g, ' ')); + await env.LEADS_DB.exec('DELETE FROM design_partner_leads'); +}); + +describe('POST /api/design-partner', () => { + it('stores a valid submission', async () => { + const res = await post(VALID); + + expect(res.status).toBe(201); + await expect(res.json()).resolves.toEqual({ ok: true }); + + const row = await env.LEADS_DB.prepare( + 'SELECT name, email, company, aws_scale, notes FROM design_partner_leads' + ).first(); + expect(row).toMatchObject({ + name: 'Grace Hopper', + email: 'grace@example.com', + company: 'Navy', + aws_scale: '2-5', + notes: 'Worried about IAM sprawl.', + }); + }); + + it('accepts a submission with only the required fields', async () => { + const res = await post({ name: 'Ada', email: 'ada@example.com' }); + + expect(res.status).toBe(201); + expect(await leadCount()).toBe(1); + }); + + it('trims whitespace and caps over-long fields', async () => { + await post({ ...VALID, name: ' Grace ', notes: 'x'.repeat(5000) }); + + const row = await env.LEADS_DB.prepare( + 'SELECT name, notes FROM design_partner_leads' + ).first<{ name: string; notes: string }>(); + expect(row?.name).toBe('Grace'); + expect(row?.notes).toHaveLength(2000); + }); +}); + +describe('honeypot', () => { + it('drops a submission with the honeypot filled, without storing it', async () => { + const res = await post({ ...VALID, website: 'http://spam.example' }); + + expect(await leadCount()).toBe(0); + }); + + it('answers 201 so a bot cannot tell which field caught it', async () => { + const trapped = await post({ ...VALID, website: 'http://spam.example' }); + const genuine = await post(VALID); + + expect(trapped.status).toBe(genuine.status); + await expect(trapped.json()).resolves.toEqual(await genuine.json()); + }); + + it('stores a submission when the honeypot is present but empty', async () => { + const res = await post({ ...VALID, website: '' }); + + expect(res.status).toBe(201); + expect(await leadCount()).toBe(1); + }); +}); + +describe('validation', () => { + it.each([ + ['a missing name', { ...VALID, name: '' }, 'Please tell us your name.'], + ['a whitespace-only name', { ...VALID, name: ' ' }, 'Please tell us your name.'], + ['a malformed email', { ...VALID, email: 'notanemail' }, 'That email address does not look right.'], + ['an email with no domain dot', { ...VALID, email: 'a@b' }, 'That email address does not look right.'], + ['an aws_scale outside the list', { ...VALID, aws_scale: 'lots' }, 'Please pick one of the listed options.'], + ])('rejects %s and stores nothing', async (_label, fields, message) => { + const res = await post(fields); + + expect(res.status).toBe(422); + await expect(res.json()).resolves.toEqual({ error: message }); + expect(await leadCount()).toBe(0); + }); + + it('allows an unstated aws_scale', async () => { + const res = await post({ ...VALID, aws_scale: '' }); + + expect(res.status).toBe(201); + expect(await leadCount()).toBe(1); + }); +}); + +describe('routing', () => { + it.each(['GET', 'PUT', 'DELETE'])('refuses %s', async (method) => { + const res = await post(VALID, method); + + expect(res.status).toBe(405); + expect(await leadCount()).toBe(0); + }); + + it('404s an unknown path rather than falling through to the handler', async () => { + const request = new Request('https://teemops.com/api/nope', { method: 'POST' }); + const ctx = createExecutionContext(); + const res = await worker.fetch(request, env, ctx); + await waitOnExecutionContext(ctx); + + expect(res.status).toBe(404); + }); +}); diff --git a/www/tsconfig.json b/www/tsconfig.json new file mode 100644 index 00000000..d0c2fb2c --- /dev/null +++ b/www/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2022", + "lib": ["es2022"], + "module": "es2022", + "moduleResolution": "bundler", + "types": ["./worker-configuration.d.ts"], + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "isolatedModules": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["src/**/*.ts", "worker-configuration.d.ts"] +} diff --git a/www/vitest.config.ts b/www/vitest.config.ts new file mode 100644 index 00000000..9924f9fd --- /dev/null +++ b/www/vitest.config.ts @@ -0,0 +1,18 @@ +import { cloudflareTest } from '@cloudflare/vitest-pool-workers'; +import { defineConfig } from 'vitest/config'; + +// @cloudflare/vitest-pool-workers 0.20 dropped the "/config" subpath and its +// defineWorkersConfig / defineWorkersProject helpers. On vitest 4 the old +// test.poolOptions.workers object is passed to the cloudflareTest() plugin +// instead — that plugin is also what provides the "cloudflare:test" module. +export default defineConfig({ + plugins: [ + cloudflareTest({ + wrangler: { configPath: './wrangler.jsonc' }, + miniflare: { + // Tests assert on row counts, so they must not share a database. + isolatedStorage: true, + }, + }), + ], +}); diff --git a/www/wrangler.jsonc b/www/wrangler.jsonc new file mode 100644 index 00000000..9f923871 --- /dev/null +++ b/www/wrangler.jsonc @@ -0,0 +1,37 @@ +{ + // Deploys teemops.com — the marketing site and its design-partner signup form. + // + // This is a SECOND Workers project in this repo. The root wrangler.jsonc is + // docs.teemops.com (see mkdocs.yml). Run wrangler from inside www/, or pass + // `-c www/wrangler.jsonc`, or you will deploy the wrong project. + // + // "name" must match the Worker shown in the Cloudflare dashboard. + "name": "tops-www", + "main": "src/index.ts", + "compatibility_date": "2026-08-06", + "compatibility_flags": ["nodejs_compat"], + + // Static pages. Requests matching a file here are served directly and never + // reach the Worker; everything else (i.e. POST /api/design-partner) does. + "assets": { + "directory": "./public", + "not_found_handling": "404-page" + }, + + // Design-partner signups. Created with `wrangler d1 create tops-www-leads`. + "d1_databases": [ + { + "binding": "LEADS_DB", + "database_name": "tops-www-leads", + "database_id": "88cc0eec-9c77-4714-8b1a-62c7db52e0e5" + } + ], + + // No secrets and no vars. The signup endpoint is protected by a honeypot field, + // not by a CAPTCHA — see "If you start getting spam" in README.md. + + "observability": { + "enabled": true, + "logs": { "head_sampling_rate": 1 } + } +}