> ## Documentation Index
> Fetch the complete documentation index at: https://docs.springwinter.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Model and Data Practices for Springwinter

> Understand what Springwinter stores, what stays in your AWS account, and how IAM roles, session cookies, and CSRF protection are managed.

Springwinter is designed so that your AWS infrastructure stays entirely within your account. The platform uses a short-lived, assumed-role model for AWS access, stores only the minimum data needed to operate, and never persists secrets it does not own. This page explains exactly what Springwinter stores, what it accesses on demand, and how access is controlled at every layer.

## What Springwinter Stores

Springwinter keeps a small operational record for each organization. The table below lists every category of data it retains on its own infrastructure.

| Category | What is stored |
| - | - |
| **Account** | Email address, hashed password, organization name |
| **AWS connection** | AWS account number, IAM role name, external ID, active status |
| **GitHub connection** | GitHub App installation ID, GitHub account handle |
| **API tokens** | Token ID and a one-way hash of the secret — the plaintext value is shown once and never stored |
| **Resource configuration** | Names, sizes, environment variable keys and values you set through Springwinter |

## What Stays in Your AWS Account

The following resources and data are created and stored exclusively in your AWS account. Springwinter never copies them to its own infrastructure.

<CardGroup cols={2}>
  <Card title="Compute & Serving" icon="server">
    ECS clusters, task definitions, services (web servers and workers), Application Load Balancers, CloudFront distributions, S3 static website buckets
  </Card>

  <Card title="Data & Storage" icon="database">
    RDS instances (PostgreSQL or MySQL), ElastiCache clusters (Valkey), private S3 storage buckets, AWS Secrets Manager secrets for database passwords
  </Card>

  <Card title="Observability" icon="chart-bar">
    CloudWatch log groups and log streams, CloudWatch metrics — Springwinter reads these on demand and never copies them
  </Card>

  <Card title="Networking" icon="network-wired">
    VPCs, subnets, security groups, NAT gateways, and all associated routing configuration created by Springwinter
  </Card>
</CardGroup>

## What Springwinter Does NOT Store

<Info>
  Springwinter intentionally avoids retaining any credentials or data that it only needs transiently:

  * **Temporary AWS credentials** — assumed per API call via `sts:AssumeRole`, discarded immediately after use, never written to disk or a database
  * **GitHub tokens** — minted per build by the GitHub App, used to clone the repository, then discarded
  * **Log data** — read from CloudWatch on demand and streamed to your browser; never indexed or stored by Springwinter
  * **Metrics data** — read from CloudWatch on demand for display; never stored by Springwinter
  * **Database passwords (plaintext)** — stored in AWS Secrets Manager in your account; Springwinter reads them on demand when needed
</Info>

## IAM Role Model

Your CloudFormation stack creates a single IAM role in your AWS account. Springwinter assumes this role only when making specific API calls on your behalf — it is never resident in Springwinter's infrastructure between calls.

<Steps>
  <Step title="You launch the CloudFormation stack">
    Springwinter provides a CloudFormation template. When you deploy it, it creates one IAM role with a trust policy that allows Springwinter's AWS account to assume it, scoped to a unique external ID generated for your connection.
  </Step>

  <Step title="Springwinter assumes the role per call">
    When you deploy a resource, view logs, or read metrics, Springwinter calls `sts:AssumeRole` with the external ID. This produces short-lived temporary credentials that expire automatically.
  </Step>

  <Step title="You control the permissions">
    The CloudFormation template defines the permissions attached to the role. Springwinter does not request administrator access. Review and adjust the policy in your AWS Console at any time to match the exact permissions Springwinter needs.
  </Step>
</Steps>

<Tip>
  Periodically open the IAM role in your AWS Console and review its attached policies. Remove any permissions that no longer correspond to resource types you actively use with Springwinter.
</Tip>

## Session Security

Browser sessions use an HttpOnly session cookie that JavaScript running in the page cannot read. This prevents session token theft via cross-site scripting.

All mutating API requests made through a browser session — `POST`, `PATCH`, `DELETE` — require a valid CSRF token retrieved from `GET /api/csrf`. Two categories of requests are exempt from the CSRF check:

<CardGroup cols={2}>
  <Card title="Bearer Token Requests" icon="key">
    Requests authenticated with `Authorization: Bearer YOUR_TOKEN` bypass the CSRF check entirely. The token itself serves as proof of intent.
  </Card>

  <Card title="GitHub Webhook" icon="github">
    Incoming webhook events from GitHub are verified using an HMAC signature computed with a shared secret. Springwinter rejects any request whose signature does not match.
  </Card>
</CardGroup>

## Security Best Practices

<Tip>
  Regularly rotate your API tokens — especially tokens used in CI/CD pipelines — and revoke any token you no longer actively use. Navigate to **Settings → API Tokens** to review and delete old tokens.
</Tip>

<Warning>
  If you suspect an API token has been exposed, revoke it immediately from **Settings → API Tokens**. Revocation takes effect instantly — all subsequent requests using that token are rejected with `401 Unauthorized`.
</Warning>
