Some checks failed
		
		
	
	Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
			
				
	
	
		
			121 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Markdown
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Markdown
		
	
	
		
			Executable File
		
	
	
	
	
| # Free‑Tier Quota — **{{ quota_anon }}/ {{ quota_token }} Scans per UTC Day**
 | ||
| 
 | ||
| Stella Ops is free for individual developers and small teams.  
 | ||
| To avoid registry abuse the scanner enforces a **two‑tier daily quota**
 | ||
| — fully offline capable.
 | ||
| 
 | ||
| | Mode | Daily ceiling | How to obtain |
 | ||
| |------|---------------|---------------|
 | ||
| | **Anonymous** | **{{ quota_anon }} scans** | No registration. Works online or air‑gapped. |
 | ||
| | **Free JWT token** | **{{ quota_token }} scans** | Email `token@stella-ops.org` (blank body). Bot replies with a signed JWT. |
 | ||
| 
 | ||
| *Soft reminder banner appears at 200 scans. Exceeding the limit never blocks –  
 | ||
| the CLI/UI introduce a delay, detailed below.*
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 1 · Token structure
 | ||
| 
 | ||
| ```jsonc
 | ||
| {
 | ||
|   "iss": "stella-ops.org",
 | ||
|   "sub": "free-tier",
 | ||
|   "tid": "7d2285…",      // 32‑byte random token‑ID
 | ||
|   "tier": {{ quota_token }}, // daily scans allowed
 | ||
|   "exp": 1767139199      // POSIX seconds (mandatory) – token expiry
 | ||
| }
 | ||
| ````
 | ||
| 
 | ||
| * The **token‑ID (`tid`)** – not the e‑mail – is hashed *(SHA‑256 + salt)*
 | ||
|   and stored for counter lookup.
 | ||
| * Verification uses the bundled public key (`keys/cosign.pub`) so **offline
 | ||
|   hosts validate tokens locally**. An optional `exp` claim may be present;
 | ||
|   if absent, the default is a far‑future timestamp used solely for schema
 | ||
|   compatibility.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 2 · Enforcement algorithm (rev 2.1)
 | ||
| 
 | ||
| | Step | Operation                                                                      | Typical latency                      |
 | ||
| | ---- | ------------------------------------------------------------------------------ | ------------------------------------ |
 | ||
| | 1    | `key = sha256(ip)` *or* `sha256(tid)`                                          | < 0.1 ms                             |
 | ||
| | 2    | `count = INCR quota:<key>` in Redis (24 h TTL)                                 | 0.2 ms (Lua)                         |
 | ||
| | 3    | If `count > limit` → `WAIT delay_ms`                                           | first 30 × 5 000 ms → then 60 000 ms |
 | ||
| | 4    | Return HTTP 429 **only if** `delay > 60 s` (should never fire under free tier) | —                                    |
 | ||
| 
 | ||
| *Counters reset at **00:00 UTC**.*
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 3 · CLI / API integration
 | ||
| 
 | ||
| ```bash
 | ||
| # Example .env                                    
 | ||
| docker run --rm \
 | ||
|   -e DOCKER_HOST="$DOCKER_HOST" \                       # remote‑daemon pointer
 | ||
|   -v "$WORKSPACE/${SBOM_FILE}:/${SBOM_FILE}:ro" \       # mount SBOM under same name at container root
 | ||
|   -e STELLA_OPS_URL="https://${STELLA_URL}" \           # where the CLI posts findings
 | ||
|   "$STELLA_URL/registry/stella-cli:latest" \
 | ||
|     scan --sbom "/${SBOM_FILE}" "$IMAGE"
 | ||
| ```
 | ||
| 
 | ||
| *No JWT? → scanner defaults to anonymous quota.*
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 4 · Data retention & privacy
 | ||
| 
 | ||
| | Data                   | Retention                            | Purpose          |
 | ||
| | ---------------------- | ------------------------------------ | ---------------- |
 | ||
| | IP hash (`quota:ip:*`) | 7 days, then salted hash only        | Abuse rate‑limit |
 | ||
| | Token‑ID hash          | Until revoked                        | Counter lookup   |
 | ||
| | E‑mail (token request) | ≤ 7 days unless newsletters opted‑in | Deliver the JWT  |
 | ||
| 
 | ||
| *No personal data leaves your infrastructure when running offline.*
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 5 · Common questions
 | ||
| 
 | ||
| <details>
 | ||
| <summary>What happens at exactly 200 scans?</summary>
 | ||
| 
 | ||
| > The UI/CLI shows a yellow “fair‑use reminder”.
 | ||
| > No throttling is applied yet.
 | ||
| > Once you cross the full limit, the **first 30** over‑quota scans incur a
 | ||
| > 5‑second delay; further excess scans delay **60 s** each.
 | ||
| 
 | ||
| </details>
 | ||
| 
 | ||
| <details>
 | ||
| <summary>Does the quota differ offline?</summary>
 | ||
| 
 | ||
| > No.  Counters are evaluated locally in Redis; the same limits apply even
 | ||
| > without Internet access.
 | ||
| 
 | ||
| </details>
 | ||
| 
 | ||
| <details>
 | ||
| <summary>Can I reset counters manually?</summary>
 | ||
| 
 | ||
| > Yes – delete the `quota:*` keys in Redis, but we recommend letting them
 | ||
| > expire at midnight to keep statistics meaningful.
 | ||
| 
 | ||
| </details>
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 6 · Revision history
 | ||
| 
 | ||
| | Version | Date       | Notes                                                               |
 | ||
| | ------- | ---------- | ------------------------------------------------------------------- |
 | ||
| | **2.1** | 2025‑07‑16 | Consolidated into single source; delays re‑tuned (30 × 5 s → 60 s). |
 | ||
| |  2.0    | 2025‑04‑07 | Switched counters from Mongo to Redis.                              |
 | ||
| |  1.0    | 2024‑12‑20 | Initial free‑tier design.                                           |
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| **Authoritative source** — any doc or website section that references quotas
 | ||
| *must* link to this file instead of duplicating text.
 |