Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • Getting Started with AI for VLSI Engineers5
  • Just Enough AI: Models and Context15
  • Prompting13
  • Trust and Verification14
  • Using AI for Engineering Work17
  • Engineering Walkthroughs7
  • Practical Foundations for AI Workflows4
  • Engineering Data5
  • Retrieval-Augmented Generation6
  • Agents and Tool Use18
  • Agent Design8
  • MCP and Skills6
  • Multi-Agent Design6
  • Practical Capstone6
  • Tokens, Cost and Latency12
  • Agentic Workflows for Chip Teams18
    • Regression Triage Agent
    • Lint-and-Fix Loops
    • Guardrails and Human in the Loop
      • Permission Tiers and Least Privilege
      • Sandboxing and Approval Gates
      • Rate, Cost Limits and Audit Logs
      • Secret Handling
      • Prompt Injection from Files and Logs
    • Evaluating and Operating Agents
  • Interview and Judgment10
  • AI Skills: Full Course Index
  • Working with AI Glossary
  • Working with AI Cheatsheet
Loading lesson

‹Guardrails and Human in the Loop
  1. Topics
  2. AI Skills for VLSI Engineers
  3. Agentic Workflows for Chip Teams
  4. Guardrails and Human in the Loop
  5. Permission Tiers and Least Privilege

Reference: Agentic Workflows for Chip Teams · Beginner to Intermediate

Permission Tiers and Least Privilege

Permission tiers from read to run, least privilege, and a policy checker with tests.

On this page

    Five permission tiers

    Each agent action carries one tier. The tier decides whether code runs, and what may change.

    Tiers are ordered by blast radius. A higher tier is never implied by a lower one.

    Tier

    Side effects

    Needs a person

    Read

    None; sources are only viewed

    No, unless the source is restricted.

    Propose

    None; output is draft text

    No, review happens at use.

    Write to scratch

    Inside one scratch directory only

    No, while paths stay inside.

    Write to repo

    Tracked sources change

    Yes, every time.

    Run jobs

    Compute runs and tool side effects

    Yes, for each named job.

    Least privilege in practice

    Least privilege means the agent holds the lowest tier that still finishes the task. A triage run starts at read and propose.

    Elevation is per action and expires. A run that edited one file does not keep repo write for its next run.

    • Default a new run to read plus propose, and add scratch only when it must write.

    • Name exact targets: file paths for writes and job names for runs.

    • Separate duties: the run that edits sources is not the run that approves them.

    A policy checker

    This is a policy-decision exercise for a fixed synthetic resource set, not a filesystem sandbox. Approval records come from a trusted controller and bind kind, target and revision; the model cannot mint them. A real executor must additionally enforce canonical filesystem containment, symlink/race protection, network restrictions and single-use approval consumption at execution time. A path string or a Boolean from the model is not authorisation.

    example.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    from pathlib import PurePosixPath
    
    READABLE = {"rtl/alu.sv", "reports/lint.txt"}
    WRITABLE = {"rtl/alu.sv"}
    JOBS = {"lint", "sim-smoke"}
    
    def safe_path(target):
        if not isinstance(target, str) or not target or chr(92) in target:
            return False
        path = PurePosixPath(target)
        parts = target.split("/")
        return (not path.is_absolute() and
                not any(p in ("", ".", "..") for p in parts) and
                not any(p in ("secrets", "keys", ".ssh", "release") for p in parts))
    
    def decide(kind, target, approval, revision="r1"):
        if kind == "propose":
            return "allow"
        if kind == "read":
            return "allow" if safe_path(target) and target in READABLE else "deny"
        if kind == "scratch":
            return "allow" if safe_path(target) and target.startswith("scratch/") else "deny"
        if kind == "repo":
            if not safe_path(target) or target not in WRITABLE:
                return "deny"
        elif kind == "run":
            if target not in JOBS:
                return "deny"
        else:
            return "deny"
        expected = (kind, target, revision)
        return "allow" if type(approval) is tuple and approval == expected else "needs-approval"
    
    
    def main():
        cases = [
            ("read", "rtl/alu.sv", False, "allow"),
            ("read", "secrets/api_key.txt", False, "deny"),
            ("propose", "draft fix plan", False, "allow"),
            ("scratch", "scratch/trial1/log.txt", False, "allow"),
            ("scratch", "../outside.txt", False, "deny"),
            ("repo", "rtl/alu.sv", False, "needs-approval"),
            ("repo", "rtl/alu.sv", ("repo", "rtl/alu.sv", "r1"), "allow"),
            ("repo", "release/tag.txt", True, "deny"),
            ("run", "lint", False, "needs-approval"),
            ("run", "lint", ("run", "lint", "r1"), "allow"),
            ("run", "deploy-prod", True, "deny"),
            ("delete-all", "rtl/", True, "deny"),
            ("repo", "/outside.sv", True, "deny"),
            ("repo", "keys/signing.pem", True, "deny"),
            ("repo", "rtl/top.sv", ("repo", "rtl/alu.sv", "r1"), "deny"),
            ("repo", "rtl/alu.sv", True, "needs-approval"),
            ("repo", "rtl/alu.sv", ("repo", "rtl/alu.sv", "old"), "needs-approval"),
        ]
        bad = 0
        allow_n = 0
        deny_n = 0
        gate_n = 0
        for (kind, target, approved, want) in cases:
            got = decide(kind, target, approved)
            if got != want:
                bad += 1
            if got == "allow":
                allow_n += 1
            elif got == "deny":
                deny_n += 1
            else:
                gate_n += 1
        if bad != 0:
            print("FAIL: %d of %d policy cases wrong" % (bad, len(cases)))
            raise SystemExit(1)
        if allow_n != 5 or deny_n != 8 or gate_n != 4:
            print("FAIL: verdict mix drifted from 5 allow, 8 deny, 4 gated")
            raise SystemExit(1)
        print("PASS: 17 policy decisions match; executor containment is a separate responsibility")
    
    
    main()

    Common mistakes

    Common pitfall

    A broad repo-write grant for a whole run invites one stray edit to touch an unrelated file. Grant the exact file per action and let the grant expire after it.

    Interview

    Likely probes: tier order and checker verdicts.

    • Read and propose have no side effects; scratch is bounded; repo and run need approval.

    • Unknown kinds and protected paths deny even when approved is true.

    • A valid approval binds the exact action, resource and revision; a generic True is insufficient.

    Check yourself A run holds scratch write. It proposes release/tag.txt. Which verdict, and why?

    Deny. Scratch covers only paths under scratch/, and release/ is a protected repo path.

    Check yourself Does an approval for rtl/alu.sv authorise rtl/top.sv or an updated diff?

    No. It is tied to the exact action, target and revision. The controller must obtain a fresh approval and enforce it at execution time; this example only models the decision.

    Related topics

    • Sandboxing and approval gates

    • Lint-and-fix loops

    Previous

    152 / 173

    Next: Sandboxing and Approval Gates

    Up next

    Up nextSandboxing and Approval Gates

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Rate, Cost Limits and Audit Logs
    • Secret Handling
    • Prompt Injection from Files and Logs