All skills

USE FOR: Drasi continuous-query solutions - real-time queries, change detection, reactive events, data-trigger pipelines on Drasi Server, Drasi for Kubernetes, or drasi-lib. Router: load bundle guides as needed. DO NOT USE for non-Drasi messaging (event-driven-messaging) or pure AKS/ACA hosting (aks-cluster-architecture, azure-container-apps).

Use this Skill: https://skilld.dev/gh/lukemurraynz/hve-agent-skills/drasi

This session only. Nothing lands on disk.

bundlessecurityguide.md

≈6.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Security bundle

Use this bundle for Drasi control-plane exposure, authentication, network boundaries, secrets, identity, RBAC, supply chain, logging hygiene, and data protection.

Secure-by-default baseline for new projects

  1. Private network access by default.
  2. Public management access only through authenticated front door or APIM.
  3. TLS everywhere outside local development.
  4. Managed identity where provider-documented and supported.
  5. Key Vault or Kubernetes Secrets for credentials, with least-privilege access.
  6. No raw secrets in YAML, source code, pipeline variables, logs, screenshots, or issue comments.
  7. No public unauthenticated access to Drasi Server REST, /api/v1/docs/, or /api/v1/openapi.json.
  8. Minimal source-system permissions.
  9. Redacted structured logs.
  10. Pinned images and dependency versions.

Control-plane exposure

Drasi Server REST APIs manage sources, queries, and reactions. Treat them as administrative APIs.

If exposed beyond a trusted local/private network, require:

  • Authentication.
  • Authorization.
  • TLS.
  • Rate limiting or abuse protection.
  • Audit logging.
  • Restricted origins if browsers are involved.
  • MCP Streamable HTTP Origin validation when MCP endpoints are reachable from browser-capable or local-network contexts.
  • Clear separation between management APIs and public application APIs.

Identity and credentials

Use this order:

  1. Microsoft Entra Workload ID where the Drasi provider or reaction documents support.
  2. Managed identity for Azure host-to-Azure-resource access.
  3. Key Vault references for Azure-hosted secrets.
  4. Kubernetes Secrets for Kubernetes-hosted provider credentials.
  5. Inline values only for disposable local examples, never production.

Verify federated credential subjects exactly. For Kubernetes-hosted providers and reactions, the service account name often includes the resource type and resource name, for example source.<name> or reaction.<name> where documented.

RBAC and least privilege

  • Source credentials should read only the data needed for the query.
  • Kubernetes Source credentials should list/watch only required resource types and scopes.
  • Reaction identities should write only to the intended downstream target.
  • CI/CD identities should deploy only the target environment.
  • Human break-glass access should be documented and audited.

Network controls

For Azure-hosted Drasi Server:

  • Prefer internal Container Apps ingress.
  • Use private endpoints or VNet integration for databases and internal dependencies where appropriate.
  • Use APIM, Application Gateway, Front Door, or equivalent only when it provides the intended auth and routing boundary.
  • Keep management API separate from public app APIs.

For Drasi for Kubernetes:

  • Do not expose internal Drasi services publicly unless docs and architecture require it.
  • Use port-forward only for local dev/test.
  • Lock down reaction services that receive callbacks or expose MCP endpoints.
  • For MCP endpoints, require authentication, TLS, Origin validation where applicable, rate limits, audit logs, and explicit resource-level data minimization.

Audit-grade verification

These are the minimum commands an auditor or operator can run to prove the security posture is actually enforced - not just documented.

TLS enforcement on a public Drasi Server endpoint

# Negotiate TLS 1.3 explicitly; expect "SSL connection using TLSv1.3" in stderr
curl -v --tlsv1.3 --tls-max 1.3 https://<drasi-host>/health 2>&1 | grep -E "TLSv1|cipher"

# Reject TLS 1.0/1.1; expect handshake failure
curl --tls-max 1.1 https://<drasi-host>/health || echo "TLS 1.1 correctly rejected"

# Confirm HSTS header is sent
curl -sI https://<drasi-host>/health | grep -i strict-transport-security

Private ingress for Drasi for Kubernetes

# Drasi services must be ClusterIP, never LoadBalancer or NodePort
kubectl -n drasi-system get svc -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.type}{"\n"}{end}'

# Confirm no public Ingress / Gateway resources expose Drasi to the internet
kubectl -n drasi-system get ingress,gateway -o wide

Supply-chain integrity

# Pin by digest; record the digest in your repo
docker pull ghcr.io/drasi-project/drasi-server:<tag>
docker inspect ghcr.io/drasi-project/drasi-server:<tag> --format '{{index .RepoDigests 0}}'

# Verify cosign signature if the publisher signs releases (re-check current publisher status before relying on this)
cosign verify ghcr.io/drasi-project/drasi-server@sha256:<digest> \
  --certificate-identity-regexp 'https://github.com/drasi-project/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

# Generate or fetch an SBOM
syft ghcr.io/drasi-project/drasi-server@sha256:<digest> -o spdx-json > drasi-server.sbom.json
grype sbom:drasi-server.sbom.json --fail-on high

Re-check the Drasi project's published signing identity and SBOM policy before relying on cosign verification - it may not be enabled on every release.

Data classification and redaction

Drasi propagates source rows through query results into reactions. Any field that is a regulated identifier (PII, PHI, payment, secret) must be classified before it leaves the source boundary.

Classification scheme to record per query

Class Examples Allowed in query result Allowed in logs Allowed in metrics/traces
Public Product IDs, statuses Yes Yes Yes
Internal Internal user IDs Yes Hash only Hash only
Confidential Email, phone, address Yes (downstream-only) Redacted Tokenized only
Restricted SSN, payment, health Avoid in result; if unavoidable, encrypted with KEK Never Never

Reaction-side redaction pattern (HTTP webhook example)

The reaction payload is the only thing a downstream system sees. Strip restricted fields and tokenize confidential ones before send. Example (illustrative):

// Source row
{"customerId": "c-12345", "email": "user@example.com", "ssn": "***", "amount": 240}

// Logged at reaction (after redaction)
{"customerId": "c-12345", "email_hash": "sha256:9f86d...", "amount": 240}

Logging rules

  • Never log full request bodies for Source or Reaction connectors. Log only the connector name, query ID, change kind, and a stable hash of the payload.
  • Never log Authorization, Cookie, or X-Api-Key headers.
  • For PostgreSQL Source: do not log the connection string. Log only the host, port, database, and a hash of the credential reference.
  • For Drasi Server REST: avoid RUST_LOG=trace or drasi_server=trace outside development. trace emits payload-level data.

Verification

# Quick grep over recent logs to catch obvious leaks
kubectl -n drasi-system logs -l app.kubernetes.io/part-of=drasi --since=1h \
  | grep -E "Bearer |Basic |password=|@example|@gmail|@outlook|[0-9]{3}-[0-9]{2}-[0-9]{4}" \
  && echo "POSSIBLE LEAK — investigate" || echo "no obvious leaks"

Record the classification matrix in the ContinuousQuery result contract (see continuous-queries/guide.md) so reaction authors know what they must redact.

Logging and data protection

Reject changes that log:

  • Authorization headers.
  • Passwords, tokens, connection strings, client secrets, or raw kubeconfigs.
  • Full event payloads containing PII, health, financial, customer, or security-sensitive data.

Prefer correlation ids, query/reaction names, operation type, status code, redacted error message, and latency.

Supply chain and release safety

  • Pin container images and actions.
  • Prefer image digests for production.
  • Record Drasi Server/platform/CLI versions.
  • Scan container images where the repository has scanning tools.
  • Keep generated manifests reviewable.
  • Treat cross-minor pre-1.0 upgrades as potentially breaking until proven safe.

Exit criteria

Security review is complete only when:

  • Management APIs and docs/OpenAPI endpoints are private or authenticated.
  • Every secret is stored through the approved mechanism for the runtime.
  • Each Source and Reaction has least-privilege credentials or identity.
  • Public or cross-network endpoints have TLS, auth, rate limiting, logging, and origin/CORS controls where relevant.
  • Logs and validation evidence are redacted.
  • Image, crate, CLI, and action versions are pinned for production paths.
  • Residual risks are recorded, especially for pre-1.0 components and MCP endpoints.

Trust boundaries and STRIDE mapping

Drasi crosses several distinct trust boundaries. Each must be analyzed against the STRIDE categories (Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege). Use this table as the starting point for a project threat model (see templates/drasi-threat-model.md).

Boundary S (Spoofing) T (Tampering) R (Repudiation) I (Information disclosure) D (Denial of service) E (Elevation of privilege)
Operator ↔ control plane (REST API) OIDC bearer / mTLS / managed identity; reject anonymous TLS in transit; signed manifests where supported Append-only audit log (see audit schema) TLS; redact secrets in error responses Rate limits at gateway; per-principal quotas RBAC scoped to namespace/resource; no shared admin tokens
Drasi ↔ source DB Per-source workload identity or rotated DB credential TLS to DB; verify server cert DB audit log + Drasi connector log with correlation id Least-privilege DB role; column-level grants where supported Connection-pool limits; read-replica preferred One identity per source; no shared DB role across sources
Drasi ↔ reaction endpoint HMAC signature over body using shared secret, or mTLS TLS; signed payload; replay window (timestamp + nonce) Reaction-side ack log with correlation id TLS; redact restricted fields before send Per-reaction concurrency and retry caps One workload identity per reaction (see "Reaction identity scope")
Agent ↔ MCP Reaction OIDC bearer or workload identity; Origin validation TLS; reject unauthenticated subscribe Audit subscribe/unsubscribe and resource read events Resource scope per token (token → allowed drasi://query/{id} set) Per-token rate limits; subscription caps Token cannot escalate to other queries or tenants
Secrets at rest N/A by design (data plane, not principal) Key Vault / Kubernetes Secret with encryption at rest; signed access policies Key Vault access log; SIEM forwarding Envelope encryption; CMK where required by policy Rotate before quota exhaustion (see rotation runbook) Access policies scoped per workload identity, not shared
drasi-lib host process ↔ embedded library Host process authenticates upstream callers; no separate Drasi auth surface Host-process integrity (signed binary, FS permissions) Host application log; correlate with library events Host-process memory isolation; no IPC surface added by drasi-lib Host-process resource limits (cgroups, ulimits) drasi-lib runs with host process privileges - host MUST drop privileges before loading

Record per-boundary residual risks in the project threat model.

Network egress controls

Ingress controls protect Drasi from being attacked. Egress controls protect everything else from a compromised Drasi component. Both are required. A tampered Reaction with unrestricted egress can exfiltrate query result rows - and therefore source data - to an attacker-controlled URL. Treat egress as a first-class boundary.

Kubernetes NetworkPolicy: deny default egress, allowlist explicitly

# Default-deny egress in the Drasi namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: drasi-system
spec:
  podSelector: {}
  policyTypes: [Egress]
  egress: []
---
# Allow a specific reaction pod to reach only its intended destination
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: reaction-<name>-egress
  namespace: drasi-system
spec:
  podSelector:
    matchLabels:
      drasi.io/resource: reaction
      drasi.io/name: <reaction-name>
  policyTypes: [Egress]
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: <destination-ns>
      ports:
        - protocol: TCP
          port: 443
    # DNS resolution
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

Apply the analogous pattern to source connectors: allow only the source DB endpoint and the Drasi control plane.

Azure Container Apps egress lockdown

For Drasi Server on Azure Container Apps, deploy into a VNet-integrated environment with workload profiles and use NSG / UDR / Azure Firewall to restrict egress to source DB private endpoints, reaction destinations, and Entra ID. Do not allow 0.0.0.0/0 egress from production environments.

Kill switch for a runaway Reaction

When a Reaction misbehaves (excess retries, suspected exfiltration, log floods), cut its network reach immediately, then scale it to zero. This stops the bleed before you debug.

# 1. Remove the reaction's egress NetworkPolicy (deny-all then applies)
kubectl -n drasi-system delete networkpolicy reaction-<name>-egress

# 2. Scale the reaction deployment to zero
kubectl -n drasi-system scale deployment reaction.<name> --replicas=0

# 3. Capture state for post-mortem
kubectl -n drasi-system logs deployment/reaction.<name> --previous --tail=2000 > runaway-reaction.log

For Azure Container Apps, the equivalent kill switch is az containerapp update --min-replicas 0 --max-replicas 0 plus removing the egress NSG rule.

Verification: prove egress is locked down

# Exec into a reaction pod and try to reach an arbitrary external endpoint
kubectl -n drasi-system exec deployment/reaction.<name> -- \
  curl --max-time 5 -sS https://example.com/ \
  && echo "EGRESS LEAK — investigate" || echo "egress correctly blocked"

Without egress controls, all other reaction controls (HMAC, redaction, audit) are bypassable: a tampered reaction can simply POST source rows to https://attacker.example/.

Secret rotation runbook

Every secret that grants access to a Drasi component or that Drasi uses to reach a source or reaction must have a rotation cadence, a rotation mechanism, and a documented Drasi-side action. The table below is the consolidated runbook.

Secret Cadence target Rotation mechanism Drasi-side action on rotation
PostgreSQL source role password 90d Key Vault rotation event or ALTER ROLE ... PASSWORD driven by an automation account If credential is consumed via env-var Secret: restart source pod. If projected via mounted file: reload (file watcher) or rolling restart. If Workload Identity: none.
SQL Server SQL auth password 90d Key Vault rotation event or ALTER LOGIN ... WITH PASSWORD Same as Postgres: env-var → restart; projected file → reload or rolling restart; Workload Identity → none.
Entra Workload ID federated credential Federated credentials do not have rotating secrets; rotate the underlying OIDC trust subject only when service account names change Update federatedIdentityCredentials subject to match new system:serviceaccount:<ns>:<name> None: token exchange happens per request; no Drasi-side restart.
Webhook (reaction) HMAC signing key 90d, or immediately on suspected compromise Generate new key in Key Vault; dual-publish for one cycle so receiver can accept old + new Roll signing key in reaction config; if env-var: restart. Verify receiver accepts new key before retiring old.
MCP bearer / API gateway token 30–90d depending on token blast radius Issue new token from identity provider; revoke old token at gateway If gateway-managed (recommended): no Drasi-side action. If Drasi reaction holds the token: env-var → restart; projected file → reload.
Container registry pull token 90d, or per platform default for managed identity ACR pull Prefer managed identity ACR pull (no token). Otherwise rotate imagePullSecret Recreate imagePullSecret; pods pick up new credential on next pull. No restart needed for already-running pods.
Drasi Server admin / break-glass credential 30d for break-glass; should be unused in steady state Manual rotation, recorded in audit log; alarm on use Restart control plane if credential is env-injected; none if served via OIDC.

Rotation principles

  • Prefer Workload Identity / managed identity wherever the provider supports it: nothing to rotate on the Drasi side.
  • For env-var secrets, expect a pod restart on rotation. Plan rolling updates so source connectors do not all restart at once.
  • For projected file secrets, use a sidecar or built-in watcher so the connector reloads without a restart where possible.
  • Dual-publish keys (old + new accepted simultaneously) for HMAC and bearer tokens so receivers never have a window of rejection.
  • Alarm on any secret older than 1.5× cadence.

Verification

# List Key Vault secrets with last-rotation timestamps
az keyvault secret list --vault-name <vault> --query "[].{name:name,updated:attributes.updated}" -o table

# Confirm no Drasi pod has been running longer than the cadence (env-var rotations require restart)
kubectl -n drasi-system get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.startTime}{"\n"}{end}'

Audit log schema

Every control-plane mutation against Drasi Server REST APIs must produce an audit record. Use this minimum schema:

Field Type Required Example
timestamp RFC 3339 UTC Yes 2026-05-15T14:22:08.412Z
principal string (subject of authenticated caller) Yes alice@contoso.com / system:serviceaccount:ops:deployer
source_ip string Yes 10.42.0.18
action string (HTTP verb + path template) Yes POST /api/v1/sources, DELETE /api/v1/queries/{id}
target object {kind, name, namespace} Yes {kind: "ContinuousQuery", name: "vehicles-on-route", namespace: "drasi-system"}
correlation_id string Yes c-7b1f...
result enum success / denied / error Yes success
request_hash sha256 of request body (NOT the body itself) Recommended sha256:9f86d...
error_class string (when result != success) Conditional AuthorizationDenied

Retention: ≥ 365 days for production. Longer if regulatory (HIPAA, PCI) applies.

Immutability: append-only sink. Write to an immutable store (Azure Storage immutability policy, AWS S3 Object Lock, or a SIEM-managed sink). The Drasi Server process must not have delete or overwrite permission on its own audit stream.

SIEM handoff: ship audit events to the SIEM in near-real-time. Recommended pattern is a sidecar or platform agent (Azure Monitor / Fluent Bit / Vector) tailing the audit stream and forwarding to the SIEM ingestion endpoint. Alarm on:

  • Any result=denied for a privileged action.
  • A burst of POST /api/v1/sources from one principal.
  • Any DELETE /api/v1/queries/{id} outside change windows.
  • Any action whose principal is not in the approved automation or human operator list.

Record audit-log location, retention, and SIEM destination in the architecture decision record.

Multi-tenancy stance

Default posture: single-tenant per Drasi instance. Pre-1.0 Drasi does not provide built-in tenant isolation. Sharing a single Drasi Server (or Drasi for Kubernetes installation) across tenants can leak data across tenant boundaries because:

  • Query results are not tenant-scoped by the platform.
  • Source replication slots (e.g., Postgres logical replication) are visible to any operator with control-plane access.
  • Reaction queues and MCP resource URIs are not tenant-namespaced.

If multi-tenancy is mandatory, isolate at the infrastructure layer using these primitives:

Primitive Mechanism
Namespace per tenant One Kubernetes namespace per tenant in Drasi for Kubernetes; NetworkPolicy enforces no cross-namespace pod-to-pod traffic.
Instance per tenant (Drasi Server) One Drasi Server deployment per tenant. Do not share a Drasi Server process across tenants.
Managed identity per tenant Distinct workload identities per tenant so a compromised tenant cannot read another tenant's source.
Gateway-enforced scope on MCP API gateway maps each token to its tenant's drasi://query/{queryId} prefix and rejects out-of-scope subscribes.
Network isolation Per-tenant NetworkPolicy / NSG; no shared egress allowlist.
Audit segregation Per-tenant audit stream so one tenant's SIEM cannot see another tenant's principals.

Explicit warning: until Drasi documents a tenancy model, treat any shared instance as a shared-fate trust domain. A tampered query in tenant A can affect tenant B's source DB load, reaction queue depth, and operator audit clarity.

Control-plane authentication

/api/v1/sources, /api/v1/queries, /api/v1/reactions, and any other mutating endpoint MUST require authentication. Accepted mechanisms (any one of):

  • OIDC bearer JWT issued by an enterprise identity provider. Validate iss (issuer), aud (audience matches Drasi Server), and exp (not expired). Reject tokens missing any of these claims.
  • mTLS with a client certificate chain anchored to an internal CA. The control plane validates the chain and pins the expected subject.
  • API gateway fronting Drasi Server with managed identity (APIM, Application Gateway with managed identity, or equivalent). Drasi Server then trusts only the gateway's caller identity (mTLS or signed header).

Shared API keys are not acceptable for production control-plane access.

Verification: unauthenticated POST must be rejected with 401

# Expect HTTP 401 (or 403); absolutely NOT 200/201
curl -s -o /dev/null -w "%{http_code}\n" \
  -X POST https://<drasi-host>/api/v1/sources \
  -H "Content-Type: application/json" \
  -d '{}'
# Expected output: 401

If this returns 200 or 201, the control plane is exposed unauthenticated. Treat as a sev-1 incident.

Reaction identity scope (preventing EOP)

Rule: scope workload identity grants as narrowly as the platform allows.

For Drasi for Kubernetes on AKS, production verification (2026-06-23) confirms per-resource service accounts:

system:serviceaccount:<namespace>:source.<source-name>
system:serviceaccount:<namespace>:reaction.<reaction-name>

Use one managed identity per source/reaction boundary where practical, or at minimum keep role assignments narrowly scoped to each downstream resource.

Re-check kubectl get pod <pod> -n <ns> -o jsonpath='{.spec.serviceAccountName}' on each upgrade and update federated credential subjects if naming patterns change.

Verification (current Drasi for Kubernetes)

# Confirm source/reaction pods use per-resource SAs
kubectl -n drasi-system get pods \
  -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.serviceAccountName}{"\n"}{end}'

# Confirm each relevant source/reaction SA has the workload identity annotation and label
kubectl -n drasi-system get sa source.<source-name> reaction.<reaction-name> \
  -o jsonpath='{.metadata.annotations}{"\n"}{.metadata.labels}{"\n"}'

# Audit role assignments on the managed identity principal
az role assignment list \
  --assignee <managed-identity-principal-id> \
  --query "[].{role:roleDefinitionName,scope:scope}" -o table

If the managed identity has overly broad role assignments (e.g. subscription-scope Contributor), narrow them to the specific resource and role needed by each source or reaction.

ContinuousQuery resource quotas (DoS prevention)

A ContinuousQuery is a long-running computation over an expanding state. Without per-query bounds, a single misbehaving query can starve every other query on the same Drasi instance. Required controls:

  • Per-query CPU and memory limits. Enforce as Kubernetes resource requests/limits on the query pod, or as a container-level limit in Drasi Server. A query with no upper memory bound will exhaust the node and OOM-kill unrelated queries.
  • Per-query result-row quota (optional but strongly recommended). Cap result-set cardinality (e.g., 100k rows max) and alarm before reaching the cap. A query whose result set has grown unbounded almost always indicates a join cardinality bug.
  • Pre-merge query review gate. Before any new or modified ContinuousQuery merges, a human reviewer must reject unbounded Cartesian joins and verify expected cardinality. See bundles/continuous-queries/guide.md for the join cardinality guidance and review checklist.
  • Runtime guardrails. Alarm on query state size, result-set growth rate, and per-query CPU. Page on sustained breach of the alarm thresholds.

A DoS in Drasi rarely looks like a flood of external traffic - it usually looks like one query whose state has quietly grown past the available memory.

drasi-lib threat surface

When Drasi is embedded via drasi-lib (rather than deployed as Drasi Server or Drasi for Kubernetes), the threat surface shifts:

  • The host process IS the trust boundary. There is no REST control plane to attack from the network. The relevant attackers are anyone who can run code in, or alter the configuration of, the host process.
  • No REST surface to protect. Skip the control-plane auth and ingress-policy sections; they do not apply.
  • Credentials live in host process config. Source DB credentials, downstream secrets, and any embedded reaction config are loaded by the host process - usually from environment variables, the host's secret store, or a managed identity. Apply the host application's secret-management discipline, not Drasi's.
  • No over-broad filesystem access for the host. If the host process writes Drasi state to disk, restrict that path. The drasi-lib state is as sensitive as the query results it produces.
  • Supply-chain audit of drasi-lib updates. Run cargo audit and cargo deny against the host crate before promoting a new drasi-lib version. Treat a new minor version of drasi-lib as a dependency upgrade requiring the same review as any other Rust dependency.
  • Restart and recovery inherit from the host. Source recovery semantics (replication slot replay, change cursor) are still owned by Drasi, but pod / process restart policy is owned by the host application's deployment. If the host crashes, the host's restart policy governs how Drasi resumes - there is no separate Drasi-managed restart.

Use this section in the threat model when the project's runtime form (recorded in the architecture decision record) is drasi-lib.

Source: SKILL.md on GitHub

1 warning8d3 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The Drasi skill package is a highly structured and security-conscious set of instructions for managing data change detection pipelines. It includes extensive documentation on threat modeling, workload identity setup on AKS, and specific guidance for preventing prompt injection when source data is fed into AI agents. All documented commands and scripts are legitimate operational tools for the Drasi platform, and no malicious patterns such as obfuscation, persistence, or data exfiltration were found.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: MEDIUM · 1 issue

Signed by skilld at 2cc2455. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated last month
metadata
{
  "last_verified": "2026-08-25"
}

README badge

README badge for lukemurraynz/hve-agent-skills/drasi