Skip to content

Commit 9dfbc61

Browse files
committed
Foundational work, code, tests, docs
0 parents  commit 9dfbc61

102 files changed

Lines changed: 12021 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copy to .env and adjust values per environment.
2+
AWS_PROFILE=sagemaker-dev
3+
AWS_REGION=us-west-2
4+
SAGEMAKER_PROJECT_NAME=threat-classifier
5+
DATA_CAPTURE_S3_PREFIX=s3://your-data-capture-bucket/prefix
6+
MODEL_MONITOR_ENABLED=true
7+
MODEL_PACKAGE_GROUP_NAME=ThreatClassifierPackageGroup
8+
COST_CENTER_TAG=SecOps
9+
ENVIRONMENT_TAG=dev
10+
APP_TAG=ThreatClassifier
11+
LOG_LEVEL=INFO

.github/copilot-instructions.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
You are an **MLOps Architect's Assistant**. Your core function is to generate code, documentation, and technical explanations that prioritize **security-by-design, FinOps (cost optimization), and MLOps operational integrity** over pure ML algorithm optimization.
2+
3+
**Always Frame Answers By:**
4+
1. **Governance & IaC:** Preferring AWS CDK/Proton for infrastructure definition, ensuring resources are **VPC-only**, use **IAM Least-Privilege**, and have correct **Cost Tags**.
5+
2. **Reliability & Monitoring:** Suggesting solutions that implement **SageMaker Model Monitor**, track **Data/Concept Drift**, and utilize **CloudWatch Alarms** for auto-rollback/alerting.
6+
3. **Efficiency & Trade-offs:** When coding Python or model logic, focus on efficiency (e.g., smaller HF models like DistilBERT, quantization, asynchronous handling) and justify choices based on **latency, cost, and maintainability**.
7+
8+
**Never:** Use public-facing endpoints without a clear security justification. Avoid suggesting unmonitored deployments. When discussing an ML model, immediately pivot to discussing its **production lifecycle** (deployment, monitoring, cost model).
9+
10+
This entire project is meant for interview readiness. I'd like you to explain each step, as we go down the checklist in an interviw friendly manner as to best prepare me for actual interview questions. Interviewers will want explanations and justifications for each decision.

.github/workflows/ci.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
branches: ["main"]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.11"
24+
25+
- name: Install Poetry
26+
uses: abatilo/actions-poetry@v2
27+
with:
28+
poetry-version: "1.8.3"
29+
30+
- name: Configure Poetry virtualenv
31+
run: poetry config virtualenvs.in-project true
32+
33+
- name: Cache Poetry downloads
34+
uses: actions/cache@v4
35+
with:
36+
path: |
37+
~/.cache/pypoetry
38+
~/.cache/pip
39+
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
40+
restore-keys: |
41+
${{ runner.os }}-poetry-
42+
43+
- name: Cache virtualenv
44+
uses: actions/cache@v4
45+
with:
46+
path: .venv
47+
key: ${{ runner.os }}-venv-${{ hashFiles('poetry.lock') }}
48+
restore-keys: |
49+
${{ runner.os }}-venv-
50+
51+
- name: Install dependencies
52+
run: |
53+
poetry install --no-interaction --no-ansi
54+
55+
- name: Lint with Ruff
56+
run: |
57+
poetry run ruff check src tests scripts
58+
59+
- name: Run tests
60+
run: |
61+
poetry run pytest
62+
63+
- name: Synthesize CDK app (guarded)
64+
env:
65+
THREAT_ENV: dev
66+
run: |
67+
poetry run python -m infra.cdk_app

.github/workflows/deploy.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Deploy
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
environment:
7+
description: "Deployment environment (dev|staging|prod)"
8+
type: choice
9+
required: true
10+
options:
11+
- dev
12+
- staging
13+
- prod
14+
upload_artifacts:
15+
description: "Upload model artifact to S3 before deploy"
16+
type: boolean
17+
default: false
18+
execute_deploy:
19+
description: "Run cdk deploy after packaging"
20+
type: boolean
21+
default: false
22+
23+
permissions:
24+
contents: read
25+
26+
jobs:
27+
deploy:
28+
runs-on: ubuntu-latest
29+
environment:
30+
name: ${{ github.event.inputs.environment }}
31+
url: https://console.aws.amazon.com/sagemaker/home
32+
33+
steps:
34+
- name: Checkout repository
35+
uses: actions/checkout@v4
36+
37+
- name: Set up Python
38+
uses: actions/setup-python@v5
39+
with:
40+
python-version: "3.11"
41+
42+
- name: Install Poetry
43+
uses: abatilo/actions-poetry@v2
44+
with:
45+
poetry-version: "1.8.3"
46+
47+
- name: Configure Poetry virtualenv
48+
run: poetry config virtualenvs.in-project true
49+
50+
- name: Cache Poetry downloads
51+
uses: actions/cache@v4
52+
with:
53+
path: |
54+
~/.cache/pypoetry
55+
~/.cache/pip
56+
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
57+
restore-keys: |
58+
${{ runner.os }}-poetry-
59+
60+
- name: Cache virtualenv
61+
uses: actions/cache@v4
62+
with:
63+
path: .venv
64+
key: ${{ runner.os }}-venv-${{ github.event.inputs.environment }}-${{ hashFiles('poetry.lock') }}
65+
restore-keys: |
66+
${{ runner.os }}-venv-${{ github.event.inputs.environment }}-
67+
${{ runner.os }}-venv-
68+
69+
- name: Install dependencies
70+
run: |
71+
poetry install --no-interaction --no-ansi
72+
73+
- name: Package and deploy via workflow
74+
env:
75+
THREAT_ENV: ${{ github.event.inputs.environment }}
76+
THREAT_DEPLOY_CONFIRM: ${{ github.event.inputs.execute_deploy && 'I_UNDERSTAND_THE_COST' || '' }}
77+
run: |
78+
args=("deploy")
79+
if [ "${{ github.event.inputs.upload_artifacts }}" = "true" ]; then
80+
args+=("--upload")
81+
fi
82+
if [ "${{ github.event.inputs.execute_deploy }}" = "true" ]; then
83+
args+=("--execute")
84+
fi
85+
poetry run python scripts/deployment_workflow.py "${args[@]}" --env "${THREAT_ENV}"

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Python artifacts
2+
__pycache__/
3+
*.py[cod]
4+
5+
# Virtual environments
6+
.venv/
7+
8+
# Tooling caches
9+
.pytest_cache/
10+
.ruff_cache/
11+
.coverage
12+
13+
# Build outputs
14+
artifacts/
15+
dist/

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"chat.agent.maxRequests": 40
3+
}

Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
.PHONY: install lint format test package deploy teardown clean distclean coverage
2+
3+
install:
4+
poetry install
5+
6+
lint:
7+
poetry run nox -s lint
8+
9+
format:
10+
poetry run nox -s format
11+
12+
test:
13+
poetry run nox -s tests
14+
15+
package:
16+
poetry run nox -s package
17+
18+
deploy:
19+
poetry run nox -s deploy
20+
21+
teardown:
22+
@echo "Teardown automation will be implemented after infrastructure scaffolding."
23+
24+
coverage:
25+
poetry run pytest --cov=alert_triage_classifier --cov-report=term-missing
26+
27+
clean:
28+
rm -rf .pytest_cache .ruff_cache dist
29+

README.md

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Threat Classifier - SageMaker Project
2+
3+
Standalone Amazon SageMaker solution for classifying security alert text by severity. Designed for easy integration into any security analytics platform.
4+
5+
## Features
6+
- Train DistilBERT on synthetic alert data *(implementation in progress)*
7+
- Deploy real-time endpoint with data capture, alarms, rollback *(scaffolding ready)*
8+
- API contract: { id, text } → { label, score, model, ts }
9+
- Cost guardrails, security best practices
10+
- Majority-class heuristic baseline with uplift reporting for interview storytelling
11+
- Ready for CI/CD, unit tests, and future SOC platform integration
12+
13+
## Quickstart
14+
1. Install Poetry and the AWS CLI v2.27.50 (see [AWS CLI setup](docs/aws-cli-setup.md)).
15+
2. `poetry install`
16+
3. `cp .env.example .env` and tailor the environment variables for your profile/region.
17+
4. `make lint` – run Ruff checks via Nox.
18+
5. `make test` – execute pytest with coverage gates.
19+
6. `make package` – build source + wheel artifacts.
20+
21+
CI runs automatically via GitHub Actions on pushes and pull requests. The pipeline installs Poetry-managed deps, enforces Ruff + Black via Nox, executes the pytest suite with coverage, and synthesizes the CDK app (dev environment) so we catch infrastructure regressions early. A separate `Deploy` workflow is manually triggered when you need to promote a build; it reuses the guarded deployment script, honors environment protection rules, and requires the `THREAT_DEPLOY_CONFIRM` acknowledgement before any `cdk deploy` executes. See [`docs/release-process.md`](docs/release-process.md) for the full release, tagging, and approval model we walk through in interviews.
22+
23+
> Training, deployment, and inference flows are being implemented in phases.
24+
> Placeholder CLI hooks surface `NotImplementedError` until their respective tasks land.
25+
26+
## Baseline heuristic & uplift tracking
27+
28+
Every training run now captures a deterministic majority-class baseline so we can articulate
29+
clear business value during interviews. Metrics JSON includes both the baseline scores and the
30+
uplift delivered by the TF-IDF + LogisticRegression pipeline. That data feeds into
31+
SageMaker Model Monitor baselines or CloudWatch dashboards, reinforcing the governance story
32+
while keeping compute costs predictable.
33+
34+
Two storyboard notebooks (`notebooks/01-eda.ipynb` and `notebooks/02-offline-eval.ipynb`) provide
35+
structured TODOs for running these analyses inside VPC-bound SageMaker notebooks. They emphasize
36+
data access guardrails, reproducible feature engineering, and ranking metrics like MAP@k/NDCG@k that
37+
roll into CI checks or rollback triggers.
38+
39+
### Environment configuration
40+
41+
All environment-specific settings (AWS accounts, VPC subnets, SageMaker instance types, FinOps tags) live under `config/*.yml`.
42+
43+
- Set `THREAT_ENV` to `dev`, `prod`, or another environment name to switch defaults.
44+
- Optionally override the entire configuration with `THREAT_CONFIG_PATH=/abs/path/to/config.yml` for ad-hoc testing.
45+
- Use `extends: relative/or/absolute/path.yml` inside a config file to layer overrides on top of shared baselines without duplicating metadata.
46+
- The loader validates that every deployment remains VPC-only, encrypted with customer-managed KMS keys, and tagged for cost allocation.
47+
48+
The CLI automatically consumes these files so training and future deployment flows always source a single, audited configuration.
49+
50+
See `docs/` and `SageMaker-Project-Plan.md` for the broader architecture roadmap.
51+
52+
## AWS CLI & IAM Requirements
53+
54+
- The project standardizes on **AWS CLI v2.27.50** to align with CDK tooling.
55+
- Use dedicated least-privilege profiles (e.g., `sagemaker-dev`) with MFA/SAML enforced.
56+
- Apply cost allocation tags (`App`, `Env`, `CostCenter`, `Owner`) to every resource; the CDK stack inherits them automatically.
57+
- Detailed installation and configuration instructions live in [`docs/aws-cli-setup.md`](docs/aws-cli-setup.md).
58+
59+
## Repository Layout
60+
61+
```
62+
├── data/ # Raw, synthetic, and monitoring datasets (no PII)
63+
├── docs/ # Project documentation and future ADRs/runbooks
64+
├── infra/ # AWS CDK application scaffolding
65+
├── notebooks/ # Exploratory analysis & demo notebooks
66+
├── scripts/ # Utility scripts (checklist automation, artifact packaging)
67+
├── src/ # Python packages for training, inference, CLI
68+
├── tests/ # Pytest suite executed by Nox/CI
69+
└── Makefile # Convenience targets wrapping Poetry + Nox
70+
This keeps deployment-ready artifacts reproducible without ad-hoc shell gymnastics-useful when interviewers probe for MLOps governance stories.
71+
72+
## Model Monitor baseline generation
73+
74+
Establish the statistics/constraints pair that SageMaker Model Monitor consumes with the new baseline helper:
75+
76+
```bash
77+
poetry run python scripts/create_monitor_baseline.py --env dev --dataset data/sample.csv
78+
```
79+
80+
- Uploads the provided dataset (or uses the pre-staged S3 object from `config/*.yml`) to the environment's baseline prefix.
81+
- Launches a data-quality processing job using the Model Monitor container and writes `statistics.json` & `constraints.json` alongside the dataset.
82+
- Honors least-privilege IAM assumptions by reusing the configured monitoring role and VPC-bound resources.
83+
84+
Re-run the script any time you refresh the synthetic dataset or introduce new features. Interview callout: this demonstrates proactive data drift detection and shows how the platform self-polices over its lifetime.
85+
86+
Use `make lint`/`make test` before pushing changes. When adding new directories, drop a short README describing intent so contributors stay aligned.
87+
88+
## Packaging trained artifacts
89+
90+
Bundle the latest training outputs into a SageMaker-compatible archive with the Poetry CLI harness:
91+
92+
```bash
93+
poetry run package-model
94+
```
95+
96+
Or call the lower-level script directly when you need custom arguments:
97+
98+
```bash
99+
poetry run python scripts/package_model_artifacts.py --env dev
100+
```
101+
102+
- Defaults to the environment's configured training output directory and writes `dist/<env>/model.tar.gz`.
103+
- Pass `--upload` to push the tarball to the environment's model artifacts bucket; uploads use the project KMS key and inherit FinOps tags so budgets stay accurate.
104+
- Override paths or S3 keys (`--source-dir`, `--output`, `--s3-key`) when replaying historical models or promoting a hotfix.
105+
- The CLI keeps uploads opt-in: set `THREAT_PACKAGE_UPLOAD=true` when you *intentionally* want to push to S3. Optional overrides include `THREAT_PACKAGE_SOURCE_DIR`, `THREAT_PACKAGE_OUTPUT_PATH`, and `THREAT_PACKAGE_S3_KEY`.
106+
107+
This keeps deployment-ready artifacts reproducible without ad-hoc shell gymnastics-useful when interviewers probe for MLOps governance stories.

0 commit comments

Comments
 (0)