Ingest large, messy data-security exports (.xlsx/.csv) into DuckDB and score them for risk. A model-agnostic DSPM kernel — bring your own data and risk matrix.
Project description
posturekit
Ingest large, messy data-security exports and score them for risk — a model-agnostic DSPM kernel. Bring your own data and your own risk matrix.
Two building blocks, usable together or apart:
ingest— load big, ugly tabular exports (.xlsx/.csv) into DuckDB in constant memory. Survives the things that break naive readers: a multi-GB inner sheet XML with a bogus<dimension>, inline strings, a report banner above the header, and duplicate column names in denormalised exports. Header rows are found by anchor column, so you don't hardcode a row number.scoring— a pure, config-driven engine that turns per-resource signals (exposure × sensitive-data × retention) into a risk score, level, SLA and remediation action. No I/O, no model calls — fully unit-testable and reusable across any resource type (mailboxes, folders, sites, drives, shares).
Install
pip install posturekit # scoring engine only (zero deps)
pip install "posturekit[ingest]" # + DuckDB / pyarrow / lxml ingest stack
Score resources
from posturekit import score_resource
profile = score_resource({
"exposure_level": "anyone",
"classifications": ["credentials", "pii"],
"sensitive_hit_count": 4200,
"age_years": 9,
})
# profile["risk_level"] -> "Critical"
# profile["remediation_priority"] -> "P1"
# profile["sla_days"] -> 7
# profile["recommended_action"] -> "Permission Removal"
# profile["risk_combinations"] -> ["sensitive_stale_and_broad", ...]
The whole model — weights, exposure scale, sensitive-class ceilings, retention
buckets, combination boosts, score→level bands, SLAs — lives in one CONFIG
dict, and every function takes a config= override. Drop in your own risk
matrix without touching the code:
score_resource(signals, config={"bands": [
{"min_score": 70, "level": "Critical", "priority": "P1", "sla_days": 3},
{"min_score": 0, "level": "Low", "priority": "P4", "sla_days": 180},
]})
Ingest an export
import duckdb
from posturekit import ingest_table
con = duckdb.connect("posture.duckdb")
ingest_table("Resources.xlsx", "resources", con, header_anchor="Path")
ingest_table("Permissions.csv", "permissions", con, header_anchor="Path")
Every column lands as VARCHAR (lossless — cast/derive at query time). The
.xlsx and .csv paths produce an identical schema for the same export, so
your downstream SQL doesn't care which format the data arrived in. For an export
whose layout you know exactly, pass header_row=12 instead of header_anchor.
End to end
from posturekit import score_batch, summarize
cur = con.execute('SELECT * FROM "resources"')
cols = [c[0] for c in cur.description]
rows = [dict(zip(cols, r)) for r in cur.fetchall()]
scored = score_batch(to_signals(r) for r in rows) # you map columns -> signals
print(summarize(scored))
# {'total': ..., 'by_level': {'Critical': ...}, 'by_combination': {...}}
See examples/demo.py for a runnable build→ingest→score→summarize.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file posturekit-0.1.0.tar.gz.
File metadata
- Download URL: posturekit-0.1.0.tar.gz
- Upload date:
- Size: 17.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d53cd557376d363ae0a02f475141bc4879b943ba82541c8f1ce9a1bbb2e9c4ca
|
|
| MD5 |
95b54298dacbaf06e7ae1d4d026da1ce
|
|
| BLAKE2b-256 |
fab6f0696c65d4313f0838be11f6a775f69b80db57361469feb078021333f155
|
Provenance
The following attestation bundles were made for posturekit-0.1.0.tar.gz:
Publisher:
release.yml on vinayvobbili/posturekit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
posturekit-0.1.0.tar.gz -
Subject digest:
d53cd557376d363ae0a02f475141bc4879b943ba82541c8f1ce9a1bbb2e9c4ca - Sigstore transparency entry: 2026437565
- Sigstore integration time:
-
Permalink:
vinayvobbili/posturekit@5ff8d4d3e454b022158ca64514f0a2b08fa9e1f8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/vinayvobbili
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5ff8d4d3e454b022158ca64514f0a2b08fa9e1f8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file posturekit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: posturekit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 14.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1b136edac339b42374cdc2dbc9eb58fc958024b6d37bedef0a2282edd73486f
|
|
| MD5 |
26f40e3eddd605300afdb722ac232dbf
|
|
| BLAKE2b-256 |
d623a076d6d03fd02402c823c3118de673daed39de77842d45f494c84ec90461
|
Provenance
The following attestation bundles were made for posturekit-0.1.0-py3-none-any.whl:
Publisher:
release.yml on vinayvobbili/posturekit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
posturekit-0.1.0-py3-none-any.whl -
Subject digest:
f1b136edac339b42374cdc2dbc9eb58fc958024b6d37bedef0a2282edd73486f - Sigstore transparency entry: 2026437702
- Sigstore integration time:
-
Permalink:
vinayvobbili/posturekit@5ff8d4d3e454b022158ca64514f0a2b08fa9e1f8 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/vinayvobbili
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5ff8d4d3e454b022158ca64514f0a2b08fa9e1f8 -
Trigger Event:
push
-
Statement type: