Skip to content

Security: dfeen87/Goodwill-KPI

Security

docs/SECURITY.md

SECURITY.md — Goodwill KPI Framework


1. Purpose

This document defines the security posture of the Goodwill KPI Framework. It establishes the threat model, access controls, data handling constraints, and operational guidelines that govern how the system is deployed and used in environments where auditability, data integrity, and organizational trust are non-negotiable.

The Goodwill KPI Framework is a read-only, stateless calculation service. Its security model is deliberately minimal: there is no persistent state, no authentication-gated write path, and no user data retained between requests. This document exists to make that posture explicit, auditable, and defensible.


2. Scope

In scope:

  • The FastAPI application (app/main.py) and its four HTTP routes
  • The goodwill.metrics pure functions and their input validation layer
  • The goodwill.config weight-loading mechanism, including environment variable handling
  • Deployment on Render.com as described in render.yaml
  • The read-only browser dashboard (app/templates/dashboard.html)

Out of scope:

  • Network infrastructure, TLS termination, and reverse-proxy configuration (responsibility of the hosting platform)
  • Identity and access management for the host environment
  • Third-party integrations or downstream consumers of the exported data
  • Modifications to goodwill/metrics.py (the equations are immutable)

3. Context

The framework exposes three deterministic goodwill equations—General Goodwill (G), Consumer Goodwill (CG), and Unified Goodwill Score (UGS)—through a stateless HTTP API. All computation occurs server-side in pure Python functions. No state is written, cached, or persisted. Each request is fully self-contained and independent of every other request.

The dashboard is a read-only interface. It does not authenticate users, store sessions, or issue tokens. It submits form data to the /api/goodwill/calculate endpoint and renders the response. The export endpoint (/api/goodwill/export) returns a file stream built entirely from the request payload and the equation outputs; no files are written to disk.

This architecture eliminates entire classes of risk—injection of persistent state, unauthorized data retrieval from a data store, and privilege escalation— by design.


4. Methodology / Approach

Threat Model

The framework follows a minimal-exposure threat model. The attack surface is bounded by:

Surface Exposure Mitigation
HTTP API inputs Numeric values, bounded [0, 100] Pydantic Field validation + metrics.py ValueError guards
Weight overrides Optional floats in request body Passed directly to pure functions; no eval, no exec
Export endpoint Request-driven file stream Built entirely from validated inputs; no disk I/O
Environment variables Weight defaults at startup Validated by config._float_env; non-finite values rejected
Dashboard HTML Static Jinja2 template No user-supplied content rendered into the template

Input Validation

All metric inputs are validated at two independent layers:

  1. Pydantic model (GoodwillInput): enforces type correctness and range constraints (ge=0, le=100, gt=0 for T) before any application logic runs.
  2. goodwill.metrics validation (_validate_metric, _validate_T, _validate_real_number): enforces the same constraints again inside the pure functions. This ensures that the math layer is safe even if called directly without going through the API.

Both layers raise explicit, descriptive errors. No silent truncation, clamping, or default substitution occurs for out-of-range inputs.

No Persistent State

The framework stores no data. It holds no database connections, no file handles, no session stores, and no in-memory caches between requests. Every request is stateless and isolated. Logs, if any, are the responsibility of the deployment platform and are not generated by the application.

Dependency Posture

Runtime dependencies are limited to FastAPI, Uvicorn, Pydantic, Jinja2, openpyxl, and their transitive dependencies. Development dependencies add pytest, httpx, and related tooling. No cryptographic libraries, authentication frameworks, or external service clients are included.


5. Governance Considerations

Auditability

Because no state is persisted, every result can be reproduced exactly by replaying the original request payload. Operators who require an audit trail must capture request/response pairs at the infrastructure layer (e.g., load balancer or reverse-proxy logs), as the application itself does not log calculations.

The export endpoint supports downstream auditability: the generated file contains every input, every weight, every term breakdown, and every final score. An auditor who receives an export file can verify each score by hand using the documented equations.

Reproducibility

All three equations are deterministic, pure functions with no external dependencies, random state, or time-based variation. Given identical inputs and identical weight configuration, results are byte-for-byte identical across runs, deployments, and Python versions within the supported range (3.11, 3.12).

Compliance Posture

The framework does not collect, store, or transmit personally identifiable information (PII). It processes only aggregated organizational metrics. Operators are responsible for ensuring that the numeric inputs they supply do not embed PII or confidential data in a form that could be reconstructed from logs.

Weight configuration is controlled via environment variables. Any deviation from default weights must be documented and traceable to an organizational decision, as weight choices directly affect score interpretation.


6. Operational Guidance

Deployment Hardening

  1. Run behind a reverse proxy. The application does not terminate TLS. All production deployments must be fronted by a TLS-terminating proxy (Render.com handles this automatically).

  2. Restrict inbound access if needed. The API has no authentication layer. If the deployment context requires access control, implement it at the infrastructure layer (e.g., IP allowlisting, OAuth2 proxy, or API gateway).

  3. Pin dependency versions. Use requirements.txt as-is. Do not upgrade dependencies without reviewing changelogs and re-running the test suite.

  4. Validate weight environment variables before deployment. Set and verify all GOODWILL_* environment variables in the deployment environment before the service starts. Invalid values will cause a ValueError at import time and prevent the service from starting.

  5. Do not expose the service on a public port without TLS in production. The Render.com deployment handles TLS termination. Self-hosted deployments must configure TLS at the proxy layer.

Vulnerability Reporting

If a security vulnerability is identified in this repository, open a private security advisory via GitHub's Security → Advisories tab. Do not disclose vulnerability details in public issues or pull requests until a fix has been prepared and reviewed.


7. Risks & Mitigations

Risk Likelihood Impact Mitigation
Malformed numeric inputs causing unexpected computation behavior Low Low Dual-layer validation (Pydantic + metrics.py) raises ValueError before any math executes
Unauthenticated access to calculation results Medium Low All results are derived from caller-supplied inputs; no confidential server-side data is exposed
Weight misconfiguration producing misleading scores Medium Medium Config validation at startup; operators must document and audit any non-default weight configuration
Dependency vulnerability in FastAPI/Pydantic/openpyxl Low–Medium Medium Monitor upstream security advisories; pin versions; re-run tests after upgrades
Export file containing sensitive inputs submitted by users Low Medium Operators must ensure that inputs do not contain PII; the framework itself does not filter or redact content
Denial of service via high-volume requests Low Low–Medium No computation-intensive loops; equations are O(1); rate limiting should be applied at the infrastructure layer if needed
Environment variable injection in CI/CD pipeline Low High Validate all GOODWILL_* environment variables in deployment pipelines; use secrets management for production

8. Summary

The Goodwill KPI Framework is a stateless, read-only calculation service with a deliberately minimal security surface. It stores no state, performs no authentication, and exposes no confidential data. Its primary security properties are input validation rigor, deterministic reproducibility, and architectural simplicity.

Operators are responsible for TLS termination, access control at the infrastructure layer, dependency management, and ensuring that the numeric inputs they supply do not embed sensitive information. Within those boundaries, the framework is designed to be deployed safely in governance-aware environments without additional application-layer security controls.

There aren't any published security advisories