aws-samples / aws-samples/sample-autonomous-cloud-coding-agents

feat(observability): CI guard to enforce attributed SDK client construction (#319 follow-up)

Open
#719 0 comments 0 reactions 0 assignees View on GitHub
enhancement observability
Dominant language
TypeScript
Stars
143
Forks
46
Avg merge
3d 9h
Merged PRs (30d)
20

Description

## Problem

#319 (PR #345) routes every AWS SDK client through an attributed factory (`makeClient`/`makeDocClient` in TS; `tenant_client`/`platform_client` in Python) so no outbound AWS call loses solution attribution. But that invariant is currently **convention-only** — a contributor can still write a naked `new S3Client({})` / `boto3.client(...)` and it compiles, passes tests, and works, silently losing attribution. This is exactly how the pattern decayed before: 5 naked SDK sites appeared on `main` *while #345 was in review*.

The factory is the easy path; this issue adds the **hard gate** that makes a naked client fail the build.

## Proposed enforcement (mirrors the repo's existing invariant-regression pattern)

- `scripts/check-ua-coverage.mjs` modeled on `scripts/check-types-sync.ts` — scans `cdk/src` + `cli/src` (TS) and `agent/src` (Python) for client construction outside the helper modules; exits non-zero on any naked site. Wire into `mise.toml` `drift-prevention` (a `build` dependency) + a `repo:local` prek hook.
- **Note:** use git-pathspec `'cdk/src/' 'cli/src/'` (directory prefix), **not** `'cdk/src/**/*.ts'` — the `**/*.ts` glob does not match files directly under `src/` and hid a bypass during #345 review (`cli/src/webhook-test.ts`).
- ESLint `no-restricted-syntax` `NewExpression[callee.name=/Client$/]` in `cdk/eslint.config.mjs` + `cli/eslint.config.mjs`, with an override disabling it in the `ua.ts` helper files (sharper than the script for the TS side).
- Python side via ruff `flake8-tidy-imports` banned-api or a `.semgrep/` rule (the latter gives the `# nosemgrep: -- ` allowlist the repo already documents).
- Optionally a ratchet-baseline variant (like `scripts/check-deadcode-ratchet.mjs`) only if debt must remain temporarily; #345 leaves the census at zero, so a hard gate should be feasible immediately.

## Acceptance

- A PR that adds a naked `new XxxClient({})` (cdk/cli) or `boto3.client(...)` (agent, outside `aws_session.py`) fails `mise run build` and the prek hook.
- The three `md/` sanitizers stay locked identical via a shared cross-language fixture.

## Context

- Builds on #319 / PR #345 (the factory).
- Depends on nothing; #345 should merge first so the census is already zero.

Contributor guide

Open the contributing guide

Research direction

Start by reading scripts/check-types-sync.ts and scripts/check-deadcode-ratchet.mjs, then inspect mise.toml, cdk/eslint.config.mjs, and cli/eslint.config.mjs. Check the existing client helpers and the three md/ sanitizers before running mise run build and the repo:local hook. Done means naked TypeScript or Python SDK construction fails both checks and the sanitizer fixtures remain identical.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, eslint, python, typescript
Domain
build-system, ci-cd, observability, tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.