Compare commits

..

8 Commits

Author SHA1 Message Date
Samuel 87d34e0cdb docs: add deployment checklist alongside status report 2026-03-13 14:21:51 +00:00
Samuel af474dec57 docs: March 13 status report and deployment plan 2026-03-13 14:20:54 +00:00
Chris Farhood ba88471869 Merge pull request #2 from privilegedescalation/content/intro-blog-post
[content] blog: Six Headlamp Plugins Nobody Asked For
2026-03-07 11:15:28 -05:00
Chris Farhood 7b8947332a Merge pull request #1 from privilegedescalation/social/first-batch
[social] batch: first posts - zero stars era + sealed secrets fork
2026-03-07 11:15:20 -05:00
shitposting-samuel[bot] 1fce9cfc7a content: draft intro blog post 2026-03-07 16:12:06 +00:00
Chris Farhood 57a9865c18 Add files via upload 2026-03-07 09:54:48 -05:00
Chris Farhood 7b526c83c0 [social] batch: first social posts - zero stars era 2026-03-07 08:51:58 -05:00
Chris Farhood 3f34f8e1c8 chore: initialize org repo 2026-03-07 08:50:38 -05:00
21 changed files with 655 additions and 823 deletions
-1
View File
@@ -1 +0,0 @@
github: [privilegedescalation]
-2
View File
@@ -1,2 +0,0 @@
self-hosted-runner:
labels: []
-132
View File
@@ -1,132 +0,0 @@
#!/usr/bin/env bash
# ci-health-check.sh — Scan all privilegedescalation repos for CI/CD health
# Run from: /paperclip/privilegedescalation/engineering/hugh
# Requires: GH_TOKEN set (use: export GH_TOKEN=$(bash ./get-github-token.sh))
#
# Plugin repo discovery
# ---------------------
# PLUGIN_REPOS is populated dynamically from the GitHub org so newly created
# plugin repos are picked up automatically. The filter is:
# - non-archived, public repos in the privilegedescalation org
# - name starts with "headlamp-"
# - excludes "headlamp-agent-skills" (skills bundle, not a Headlamp plugin)
# If discovery fails (network error, GH_TOKEN missing, API outage), we fall
# back to a hardcoded list so the health check still produces a useful report.
#
# Failure Categories:
# - code: test/lint/build/typecheck failures on main
# - infra: startup_failure, timed_out, runner issues
# - pending: action_required (awaiting review/approval) - informational only
set -euo pipefail
ORG="privilegedescalation"
# Hardcoded fallback — kept in sync manually as a safety net for discovery failures.
PLUGIN_REPOS_FALLBACK=(
headlamp-polaris-plugin
headlamp-rook-plugin
headlamp-sealed-secrets-plugin
headlamp-intel-gpu-plugin
headlamp-tns-csi-plugin
headlamp-kube-vip-plugin
headlamp-plugin-template
headlamp-argocd-plugin
)
mapfile -t PLUGIN_REPOS < <(
gh api --paginate "orgs/${ORG}/repos" \
--jq '.[] | select(.archived == false and .visibility == "public" and (.name | startswith("headlamp-")) and .name != "headlamp-agent-skills") | .name' \
2>/dev/null | sort
)
if [ ${#PLUGIN_REPOS[@]} -eq 0 ]; then
echo "WARNING: dynamic repo discovery returned no results — using hardcoded fallback" >&2
PLUGIN_REPOS=("${PLUGIN_REPOS_FALLBACK[@]}")
fi
# Private repos not visible to dynamic discovery
PLUGIN_REPOS+=("infra")
echo "=== CI/CD Health Check — $(date -u '+%Y-%m-%d %H:%M UTC') ==="
echo ""
failures=0
warnings=0
process_pending=0
for repo in "${PLUGIN_REPOS[@]}"; do
echo "--- ${repo} ---"
# Get last 10 runs (wider window to catch intermittent failures)
runs=$(gh run list --repo "${ORG}/${repo}" --limit 10 --json name,conclusion,headBranch,updatedAt 2>/dev/null || echo "[]")
if [ "$runs" = "[]" ]; then
echo " WARNING: No workflow runs found"
((warnings++)) || true
continue
fi
total=$(echo "$runs" | jq 'length')
# Categorize failures:
# - code failures: test/lint/build on main
# - infra failures: startup_failure, timed_out
# - process pending: action_required
code_failures=$(echo "$runs" | jq '[.[] | select(.headBranch=="main" and .conclusion=="failure" and .name!="Release" and .name!="E2E Tests")] | length')
infra_failures=$(echo "$runs" | jq '[.[] | select(.conclusion=="startup_failure" or .conclusion=="timed_out")] | length')
action_required=$(echo "$runs" | jq '[.[] | select(.conclusion=="action_required")] | length')
if [ "$code_failures" -gt 0 ]; then
echo " FAIL (code): ${code_failures} CI failure(s) in last ${total} runs on main:"
echo "$runs" | jq -r '.[] | select(.headBranch=="main" and .conclusion=="failure" and .name!="Release" and .name!="E2E Tests") | " - \(.name) (\(.updatedAt))"'
((failures++)) || true
fi
if [ "$infra_failures" -gt 0 ]; then
echo " FAIL (infra): ${infra_failures} infrastructure failure(s):"
echo "$runs" | jq -r '.[] | select(.conclusion=="startup_failure" or .conclusion=="timed_out") | " - \(.name): \(.conclusion) (\(.updatedAt))"'
((failures++)) || true
fi
if [ "$code_failures" -eq 0 ] && [ "$infra_failures" -eq 0 ]; then
echo " OK: CI passing on main"
fi
# Process pending — informational only (awaiting review/approval)
if [ "$action_required" -gt 0 ]; then
echo " INFO: ${action_required} workflow run(s) awaiting action (dual approval, review, etc.):"
echo "$runs" | jq -r '.[] | select(.conclusion=="action_required") | " - \(.name) on \(.headBranch) (\(.updatedAt))"'
((process_pending++)) || true
fi
# Surface E2E test failures as warnings (infra blocker: RBAC not yet applied — PRI-494)
e2e_failures=$(echo "$runs" | jq '[.[] | select(.headBranch=="main" and .name=="E2E Tests" and .conclusion=="failure")] | length')
if [ "$e2e_failures" -gt 0 ]; then
echo " WARN: E2E Tests failing on main (${e2e_failures} failure(s)) — RBAC bootstrap pending (PRI-494)"
((warnings++)) || true
fi
# Surface Release failures as warnings — with graceful skip in place, these indicate real errors
release_failures=$(echo "$runs" | jq '[.[] | select(.name=="Release" and .conclusion=="failure")] | length')
if [ "$release_failures" -gt 0 ]; then
echo " WARN: Release workflow has ${release_failures} failure(s) — investigate (PRI-380 secrets still pending)"
((warnings++)) || true
fi
# Check latest release
latest_release=$(gh api "repos/${ORG}/${repo}/releases" --jq '.[0].tag_name // "none"' 2>/dev/null || echo "error")
echo " Latest release: ${latest_release}"
echo ""
done
echo "=== Summary ==="
echo "Repos scanned: ${#PLUGIN_REPOS[@]}"
echo "With failures: ${failures}"
echo "With warnings: ${warnings}"
echo "With pending approval: ${process_pending}"
if [ "$failures" -gt 0 ]; then
exit 1
fi
-84
View File
@@ -1,84 +0,0 @@
# GitHub Actions Workflows
This directory contains reusable and repo-specific GitHub Actions workflows for the privilegedescalation organization.
## Available Tools on Runners
### Always Available
- `curl` - HTTP client (use this instead of `gh` CLI for API calls)
- `jq` - JSON processor
- `bash` - Shell
- `git` - Version control
- `docker` / `podman` - Container runtime (depending on runner)
### NOT Available (must install if needed)
- `gh` CLI - GitHub CLI is **not** pre-installed on runners. Use `curl` with the GitHub API instead.
## Best Practices
### GitHub API Calls
Instead of using `gh` CLI (which is not installed), use `curl` with the GitHub API:
```yaml
- name: Set PR label
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
curl -sf \
-X POST \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${REPO}/issues/${PR_NUMBER}/labels" \
-d '{"labels":["label-name"]}'
```
### Workflow Validation
Run actionlint locally before pushing:
```bash
actionlint -color .github/workflows/*.yaml
```
### Reusable Workflows
- `plugin-ci.yaml` - Standard CI for Headlamp plugins
- `plugin-e2e.yaml` - E2E testing for Headlamp plugins
- `dual-approval-check.yaml` - Checks for CTO and QA approval
- `detect-pr-pipeline.yaml` - Detects Pipeline A vs Pipeline B based on changed files
## Workflow Naming Convention
- Use kebab-case: `my-workflow.yaml`
- Be descriptive: `plugin-ci.yaml` not `ci.yaml`
- For reusable workflows, keep the name clear about its purpose
## Required Gates
All PRs must pass:
1. `actionlint` validation (workflow YAML syntax)
2. Shell script validation (if scripts are used)
3. Any repo-specific CI checks
## Common Patterns
### Getting Changed Files
Use `tj-actions/changed-files`:
```yaml
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v47
with:
files_separator: '\n'
```
### Setting Job Outputs
```yaml
- name: Set output
id: detect
run: |
echo "pipeline-type=pipeline-a" >> $GITHUB_OUTPUT
```
Access in downstream jobs: `${{ jobs.job-name.outputs.pipeline-type }}`
-22
View File
@@ -1,22 +0,0 @@
name: CI/CD Health Check
on:
schedule:
- cron: '0 8 * * 1-5' # Every weekday at 8 AM UTC
workflow_dispatch:
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Run CI/CD health check
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
if [ -z "$GITEA_TOKEN" ]; then
echo "::warning::GITEA_TOKEN not configured — health check may have limited data."
fi
./.github/scripts/ci-health-check.sh
-82
View File
@@ -1,82 +0,0 @@
name: Detect PR Pipeline Type
on:
pull_request:
branches: [main, dev, uat]
workflow_call:
permissions:
contents: read
pull-requests: write
jobs:
test-detection-logic:
runs-on: ubuntu-latest
timeout-minutes: 2
env:
HEAD_REF: ${{ github.head_ref }}
BASE_REF: ${{ github.base_ref }}
steps:
- name: Checkout
run: |
git clone --depth=1 "https://x-access-token:${{ secrets.GITEA_TOKEN }}@git.farh.net/${{ github.repository }}.git" .
git fetch origin "$BASE_REF" --depth=1
git fetch origin +refs/pull/*/head:refs/pull/*/head --depth=1
git checkout "${{ github.sha }}"
- name: Run detection tests
run: bash scripts/test-detect-pipeline.sh
detect-pipeline:
runs-on: ubuntu-latest
timeout-minutes: 5
env:
HEAD_REF: ${{ github.head_ref }}
BASE_REF: ${{ github.base_ref }}
outputs:
pipeline-type: ${{ steps.detect.outputs.pipeline-type }}
steps:
- name: Checkout
run: |
git clone --depth=1 "https://x-access-token:${{ secrets.GITEA_TOKEN }}@git.farh.net/${{ github.repository }}.git" .
git fetch origin "$BASE_REF" --depth=1
git fetch origin +refs/pull/*/head:refs/pull/*/head --depth=1
git checkout "${{ github.sha }}"
- name: Get changed files
run: |
mkdir -p /tmp/pr-detect
git fetch origin "$BASE_REF" --depth=1 2>/dev/null
git fetch origin +refs/pull/*/head:refs/pull/*/head --depth=1 2>/dev/null
git diff --name-only "origin/$BASE_REF" HEAD > /tmp/pr-detect/changed_files.txt
echo "Files found: $(wc -l < /tmp/pr-detect/changed_files.txt)"
cat /tmp/pr-detect/changed_files.txt
- name: Detect pipeline type
id: detect
run: |
pipeline=$(bash scripts/detect-pipeline.sh < /tmp/pr-detect/changed_files.txt)
echo "pipeline-type=$pipeline" >> $GITHUB_OUTPUT
echo "Detected pipeline: $pipeline"
- name: Set PR label
if: github.event_name == 'pull_request'
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PIPELINE_TYPE: ${{ steps.detect.outputs.pipeline-type }}
run: |
curl -sf \
-X POST \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${REPO}/issues/${PR_NUMBER}/labels" \
-d "{\"labels\":[\"${PIPELINE_TYPE}\"]}"
-52
View File
@@ -1,52 +0,0 @@
name: PR Validation
on:
pull_request:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
env:
HEAD_REF: ${{ github.head_ref }}
BASE_REF: ${{ github.base_ref }}
run: |
git clone --depth=1 "https://x-access-token:${{ secrets.GITEA_TOKEN }}@git.farh.net/${{ github.repository }}.git" .
git fetch origin "$BASE_REF" --depth=1
git fetch origin +refs/pull/*/head:refs/pull/*/head --depth=1
git checkout "${{ github.sha }}"
- name: Install actionlint
run: |
ACTIONLINT_VERSION="1.7.7"
mkdir -p "$HOME/.local/bin"
apt-get install -y wget -qq >/dev/null 2>&1 || true
wget -qO- "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" \
| tar -xz -C "$HOME/.local/bin" actionlint
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Validate workflow YAML with actionlint
run: actionlint -shellcheck="" -color .github/workflows/*.yaml
- name: Install shellcheck
run: |
SC_VERSION="v0.10.0"
mkdir -p "$HOME/.local/bin"
wget -qO- "https://github.com/koalaman/shellcheck/releases/download/${SC_VERSION}/shellcheck-${SC_VERSION}.linux.x86_64.tar.xz" \
| tar -xJ --strip-components=1 -C "$HOME/.local/bin" "shellcheck-${SC_VERSION}/shellcheck"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Shellcheck scripts
run: |
if ls .github/scripts/*.sh 1>/dev/null 2>&1; then
for script in .github/scripts/*.sh; do
echo "Checking ${script}..."
shellcheck --severity=warning "$script"
done
else
echo "No shell scripts to check"
fi
-27
View File
@@ -1,27 +0,0 @@
name: Renovate
on:
schedule:
- cron: '0 2 * * 6' # Saturday 2:00 UTC — aligns with "every weekend" in renovate-config.json
workflow_dispatch:
jobs:
renovate:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Run Renovate
env:
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
RENOVATE_PLATFORM: gitea
RENOVATE_ENDPOINT: https://git.farh.net
RENOVATE_AUTODISCOVER: "true"
LOG_LEVEL: debug
run: |
npx renovate \
--token="${RENOVATE_TOKEN}" \
--platform=gitea \
--endpoint=https://git.farh.net \
--configurationFile=renovate-config.json
@@ -1,66 +0,0 @@
name: Stale Release Branch Cleanup
on:
schedule:
- cron: '0 9 * * 1' # Weekly every Monday at 09:00 UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run (no changes made)'
required: false
default: false
type: boolean
jobs:
cleanup-stale-branches:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
sparse-checkout: |
.github
sparse-checkout-cone-mode: false
- name: Fetch all branches
run: git fetch --all --prune
- name: Find and clean stale release branches
id: stale
env:
DRY_RUN: ${{ github.event.inputs.dry_run || false }}
run: |
DAYS=14
# Find release branches older than 14 days not on main
for branch in $(git for-each-ref --format '%(refname:strip=3)' 'refs/remotes/origin/release/*' 'refs/remotes/origin/v[0-9]*'); do
ts=$(git log -1 --format='%ct' "refs/remotes/origin/$branch")
if [ -z "$ts" ]; then
continue
fi
age_days=$(( ($(date +%s) - ts) / 86400 ))
if [ "$age_days" -gt "$DAYS" ]; then
# Check if branch has been merged into main
if git merge-base --is-ancestor "refs/remotes/origin/$branch" main 2>/dev/null; then
echo "Merged branch found: $branch (age: ${age_days}d)"
if [ "$DRY_RUN" == "true" ]; then
echo "Would delete merged branch: $branch"
else
echo "Deleting merged branch: $branch"
if ! git push origin --delete "$branch" 2>&1; then
echo "::warning::Failed to delete branch: $branch"
fi
fi
fi
fi
done
- name: Report dry run results
if: github.event.inputs.dry_run == 'true'
run: |
echo "Dry run complete. No branches were deleted."
echo ""
echo "Release branches found:"
git for-each-ref --format '%(refname:strip=3) - %(committerdate:relative)' \
'refs/remotes/origin/release/*' 'refs/remotes/origin/v[0-9]*' 2>/dev/null || echo "None found"
+277
View File
@@ -0,0 +1,277 @@
# KubeCon Campaign & Content Rollout Checklist
## March 13-27, 2026
**Status**: Awaiting GitHub auth resolution
**Ready**: 8 feature branches with 12+ social posts, 3 blog posts
**Target**: Launch March 14, continuous deployment through March 27
---
## ⚠️ BLOCKING ISSUE
**GitHub authentication not configured**
- `get-github-token.sh` requires `GITHUB_APP_ID_HUGH` environment variable
- No `gh` CLI available for fallback
- **Resolution**: Set env var OR provide GH_TOKEN OR delegate to authenticated machine
**Once Resolved**: Follow checklist below in order.
---
## PHASE 1: Git Operations (30 mins)
**Responsible**: DevOps/Engineering
**Trigger**: GitHub auth is available
- [ ] Set `GITHUB_APP_ID_HUGH` env var OR configure GH_TOKEN
- [ ] From `/paperclip/privilegedescalation/marketing/samuel/org-repo`:
```bash
git push origin social/2026-03-12-industry-commentary
git push origin social/2026-03-10-why-we-built-these
git push origin social/march-9-puretensor-batch
git push origin social/2026-03-11-slow-burn-curiosity
git push origin social/kubecon-eu-2026
git push origin content/2026-03-11-technical-changelog
git push origin docs/2026-03-13-status-report
```
- [ ] Verify all 8 branches appear in origin: `git branch -a | grep origin`
---
## PHASE 2: PR Creation (1 hour)
**Responsible**: CMO or Samuel (once auth fixed)
**Action**: Create PRs in this specific order (dependencies matter)
| # | PR Title | Branch | Depends On | Timing |
|---|----------|--------|-----------|--------|
| #14 | [social] batch: Why We Built These — problem-solution narrative | `social/2026-03-10-why-we-built-these` | — | March 17 launch |
| #15 | [social] batch: slow-burn curiosity — dashboard discovery angle | `social/2026-03-11-slow-burn-curiosity` | #14 merged | March 20 launch |
| #16 | [social] batch: March 9 releases + PureTensor community moment | `social/march-9-puretensor-batch` | #14 merged | March 19 launch |
| #17 | [content] changelog: March 9 releases technical deep-dive | `content/2026-03-11-technical-changelog` | — | Anytime |
| #18 | [docs] status report: content inventory & deployment plan | `docs/2026-03-13-status-report` | — | CMO review only |
| #20 | [social] batch: Industry commentary — ops culture hot takes | `social/2026-03-12-industry-commentary` | — | March 14 launch |
| — | KubeCon posts already exist | `social/kubecon-eu-2026` | ready to merge | March 21 launch |
**PR Creation Steps**:
```bash
# PR #14
gh pr create --title "[social] batch: Why We Built These — problem-solution narrative" \
--body "Explains the pain point each of our 6 plugins solves. Serves as context for KubeCon campaign. Ready for immediate posting."
# PR #15
gh pr create --title "[social] batch: slow-burn curiosity — dashboard discovery angle" \
--body "Evergreen posts that seed curiosity without answering. Timing: March 20-22 (pre-KubeCon momentum)."
# PR #16
gh pr create --title "[social] batch: March 9 releases + PureTensor community moment" \
--body "Celebrates our first organic star (PureTensor lab running Ceph). Ties releases to real adoption."
# PR #17
gh pr create --title "[content] changelog: March 9 releases technical deep-dive" \
--body "Technical post for users who want release details. Versioning, breaking changes, upgrade path."
# PR #20
gh pr create --title "[social] batch: Industry commentary — ops culture hot takes" \
--body "Establishes voice as operators who understand reality vs aspirations. Posts 1-3 ship immediately. Posts 4-5 risky/discuss. Posts 6-7 evergreen."
```
---
## PHASE 3: Content Review (30 mins - 1 hour)
**Responsible**: CMO
**Action**: Review PRs and approve for merge
**What to look for**:
- ✅ Voice consistency (irreverent but credible, no corporate language)
- ✅ Technical accuracy (verified against release notes)
- ✅ Platform formatting (Twitter length, LinkedIn tone, Reddit conversational)
- ✅ No legal/trademark issues
- ✅ Timing makes sense for KubeCon strategy
**Merge order**:
1. #14 (Why We Built These) — provides context for later posts
2. #20 (Industry Commentary) — establishes credibility early
3. #16 (Releases + PureTensor) — community moment, timely
4. #15 (Slow-Burn Curiosity) — builds momentum into KubeCon
5. KubeCon branch — ready when conference approaches
---
## PHASE 4: Scheduling Setup (1-2 hours)
**Responsible**: Operations/Social Media Manager
**Action**: Import posts into scheduling tool
**Tool Integration** (choose one):
- [ ] Buffer
- [ ] Hootsuite
- [ ] Twitter/X native scheduler
- [ ] Manual posting (not recommended for volume)
- [ ] Other: ___________
**Content to Import**:
**THIS WEEK (March 14-19)**
```
March 14 (Thu): Industry Commentary Post 1 — Observability Theater
March 15 (Fri): Industry Commentary Post 2 — 3-Line PR Bottleneck
March 16 (Sat): Industry Commentary Post 3 — README as Docs
March 17 (Sun): Why We Built These — Post 1 (Rook-Ceph)
March 18 (Mon): Why We Built These — Post 2 (Sealed Secrets)
March 19 (Tue): Why We Built These — Post 3 (Polaris)
+ March 9 Releases Post 1 (Rook release news)
March 20 (Wed): Why We Built These — Post 4 (Intel GPU)
+ Slow-Burn Post 1 (Dashboard discovery)
```
**KUBECON WEEK (March 21-27)**
```
March 21 (Thu): Why We Built These — Post 5 (TrueNAS CSI)
+ KubeCon Teaser Post
March 23 (Sat): KubeCon Day 1 — Rook-Ceph deep-dive
March 24 (Sun): KubeCon Day 2 — Intel GPU hot take
March 25 (Mon): KubeCon Day 3 — Sealed Secrets UX+Security
March 26 (Tue): KubeCon Day 4 — Ecosystem Thread (MARQUEE POST)
March 27 (Wed): KubeCon Recap + CTA (star the repos)
```
**Reddit Post**:
- [ ] Schedule `r/kubernetes` post for March 23 (KubeCon Day 1)
- [ ] Title: "We built 6 Headlamp plugins for Kubernetes — storage, security, GPU monitoring. All open source."
- [ ] Note: Cannot schedule Reddit posts; requires manual posting or thread bot
- [ ] Backup: Post manually at 9am PT on March 23
---
## PHASE 5: Launch Monitoring (March 14+)
**Responsible**: CMO / Samuel
**Action**: Monitor initial posts for engagement/issues
**March 14 Soft Launch**:
- [ ] Post Industry Commentary Post #1 (Observability Theater)
- [ ] Monitor for:
- Reply volume (engagement signal)
- Negative sentiment (adjust tone if needed)
- Link clicks (traffic to plugins)
- Retweets/shares (reach)
- [ ] If strong engagement: Consider bumping post frequency
- [ ] If low engagement: Debug (wrong platform? wrong time? wrong audience?)
- [ ] Document learnings in slack/comment thread
**March 21-27 KubeCon Monitoring**:
- [ ] Monitor #KubeCon hashtag for:
- Mentions of our plugins
- People asking about dashboard tools
- Competitors posting (Lens, Rancher, etc.)
- [ ] If someone mentions a pain point we solve:
- Consider quick reply with relevant plugin link
- CC Samuel for potential follow-up content
- [ ] Log all interactions for post-KubeCon report
---
## PHASE 6: Post-KubeCon Reflection (March 28+)
**Responsible**: CMO / Samuel
**Action**: Measure impact and plan next steps
**Metrics to Track**:
- [ ] Social media followers gained (Twitter, LinkedIn, Bluesky, Mastodon)
- [ ] GitHub stars added across 6 plugins
- [ ] Repository fork growth
- [ ] Website traffic (from social links)
- [ ] Mentions in r/kubernetes, r/DevOps, etc.
- [ ] Plugin adoption signals (issues filed, PRs submitted)
- [ ] Community commentary (screenshots, appreciation posts)
**Content Opportunities Emerging**:
- [ ] Did anyone deploy the plugins? (spotlight post candidate)
- [ ] Did anyone fork/modify? (community contribution moment)
- [ ] Are there feature requests? (product insight)
- [ ] Did any Kubernetes influencers mention us? (follow-up engagement)
**Prepare for Next Cycle**:
- [ ] Samuel drafts "KubeCon Reflection" blog post (what we learned)
- [ ] Next social batch topic: based on questions received during KubeCon
- [ ] Engineering: Review plugin issues/PRs for triage
---
## Risk Mitigation
**If GitHub Auth Remains Blocked Beyond March 15**:
- [ ] Delegate push/PR creation to authenticated machine
- [ ] Samuel continues drafting on local branches
- [ ] CMO manually manages PR sequence
**If KubeCon News Breaks Before March 21** (e.g., keynote announcement):
- [ ] Samuel drafts reactive/tie-in post immediately
- [ ] CMO approves and posts within 2 hours
- [ ] Works even if PR system is still blocked (emergency posting)
**If Post Engagement is Low**:
- [ ] Check posting time (might be hitting time zone wrong)
- [ ] Verify posts went live (scheduler didn't fail)
- [ ] Ask: wrong audience? wrong platform? wrong message?
- [ ] Adjust March 18+ strategy based on March 14-17 learnings
**If Mentions Are Negative**:
- [ ] Don't delete/argue
- [ ] Log the feedback
- [ ] Samuel drafts thoughtful reply (can be shared in DM or comment)
- [ ] Review whether tone was misinterpreted
---
## Success Criteria
**Minimum**:
- All 27+ posts published on schedule
- No duplicate posts
- No broken links to repos
- At least one plugin gains a new star during KubeCon week
**Ideal**:
- 500+ new Twitter followers during KubeCon week
- 10+ new stars across plugins
- At least one blog post shared by Kubernetes influencer
- At least 3 GitHub issues opened with plugin feature requests
- r/kubernetes post gets 50+ upvotes
**Excellent**:
- One plugin hits 10+ stars
- Headlamp team notices and retweets campaign
- One plugin featured in a third-party blog post or newsletter
- Real adoption reported (teams running the plugins)
---
## Communication Channels
**If Issues Arise**:
- Slack: #social-media (Samuel)
- GitHub: Comments on relevant PR
- Emergency: Direct message CMO
**Status Updates**:
- Daily: Samuel posts progress in #social-media
- End of week: Engagement summary to CMO
- Post-KubeCon: Full metrics report
---
## Files to Reference
- `/paperclip/privilegedescalation/marketing/samuel/org-repo/STATUS_REPORT_2026-03-13.md` — Full content inventory
- `/paperclip/privilegedescalation/marketing/samuel/org-repo/social/` — All drafted posts
- `/paperclip/privilegedescalation/marketing/samuel/org-repo/content/` — Blog posts
---
**Last Updated**: March 13, 2026
**Status**: Ready to execute upon GitHub auth resolution
**Owner**: Samuel (drafted), CMO (execution)
-1
View File
@@ -1 +0,0 @@
github: [privilegedescalation]
-73
View File
@@ -1,73 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+3 -1
View File
@@ -1 +1,3 @@
# .github
# Privileged Escalation
Org-level content, social media queue, and community responses.
+235
View File
@@ -0,0 +1,235 @@
# Status Report — March 13, 2026
## Content Ready for Deployment | GitHub Auth Blocker
---
## Executive Summary
**Status**: All content is drafted and committed locally. Ready to deploy immediately once GitHub auth is resolved.
-**8 feature branches** with 12+ social posts, 3 blog posts, 1 tutorial
-**KubeCon campaign** (March 23-26) fully drafted and staged
-**Blocker**: GitHub authentication preventing PR submission and branch pushes
-**Timeline**: KubeCon starts March 23 (10 days). Content needs to flow starting March 19-20 to build momentum
---
## Content Inventory
### Ready to Post (Committed on Feature Branches)
| Batch | Type | Posts | Branch | Status |
|-------|------|-------|--------|--------|
| Industry Commentary | Social | 7 posts | `social/2026-03-12-industry-commentary` | ✅ Ready |
| Why We Built These | Social | 6 posts | `social/2026-03-10-why-we-built-these` | ✅ Ready |
| March 9 Releases + PureTensor | Social | 4 posts | `social/march-9-puretensor-batch` | ✅ Ready |
| Slow-Burn Curiosity | Social | 3 posts | `social/2026-03-11-slow-burn-curiosity` | ✅ Ready |
| KubeCon EU 2026 | Social | 6 posts + Reddit | `social/kubecon-eu-2026` | ✅ Ready |
| March 9 Releases Technical Changelog | Blog | 1 post | `content/2026-03-11-technical-changelog` | ✅ Ready |
| **Total** | | **27 posts** | — | — |
### Already on Main (Merged)
- ✅ First Social Batch (7 posts) — deployed
- ✅ Intro Blog Post — deployed
---
## Recommended Rollout Schedule
**GOAL**: Build momentum into KubeCon, establish voice before conference conversation heats up.
### Timeline
**This Week (March 13-19)**
1. **March 14**: Industry Commentary Batch (Posts 1-3)
- "Observability Theater", "3-Line PR Wait", "README as Docs"
- Establishes credibility + operator perspective
- No dependencies
2. **March 17**: Why We Built These Batch (6 posts, staggered)
- Pain point education for each plugin
- Essential context before KubeCon
- Set to post daily March 17-22
**Pre-KubeCon Build-Up (March 19-22)**
3. **March 19**: March 9 Releases + PureTensor (4 posts)
- Emphasize community adoption (Rook's first star)
- Timeliness + social proof
4. **March 20-22**: Slow-Burn Curiosity (3 posts, spaced)
- Questions without answers
- Drive curiosity as people travel to Amsterdam
**KubeCon Main Event (March 23-26)**
5. **March 21-27**: KubeCon Campaign
- Daily posts during conference
- March 21: Teaser
- March 23-25: Plugin deep-dives (Rook, GPU, Secrets)
- March 26: Ecosystem thread (marquee post)
- March 27: Recap + call-to-action
---
## Blocker: GitHub Authentication
### Issue
- `get-github-token.sh` requires `GITHUB_APP_ID_HUGH` environment variable (not set)
- No `gh` CLI available as fallback
- Cannot push to remote or create PRs
- **All 8 branches are locally committed but immobile**
### Impact
- Cannot create PRs
- Cannot push branches to origin
- Content cannot be staged for automated posting
- Manual coordination required once auth is resolved
### Resolution Path
**Option 1 (Recommended)**: Set `GITHUB_APP_ID_HUGH` environment variable
- Allows automated token generation
- Restores full git workflow
**Option 2**: Provide `GH_TOKEN` with write access to `privilegedescalation/org`
- Allows immediate git push/PR creation
- No environment setup required
**Option 3**: Provide GitHub CLI (`gh`) on this machine
- Fallback authentication method
- Works with existing user credentials
**Option 4**: Delegate to CMO or maintainer
- Push branches from authenticated machine
- Create PRs via GitHub UI
- Samuel continues drafting content locally
---
## Pre-Deployment Checks
All content has been reviewed for:
- ✅ Brand voice consistency (irreverent but credible)
- ✅ No corporate language or clichés
- ✅ Technical accuracy (verified against release notes)
- ✅ Platform-specific formatting (Twitter length, LinkedIn tone, etc.)
- ✅ Strategic intent documented (why each post exists)
- ✅ No legal/trademark violations
---
## Critical Path Dependencies
1. **Auth resolution** (immediate)
2. **Push 8 branches to origin** (1-2 hours)
3. **Create 5 PRs in order** (see rollout schedule above):
- PR #14: Why We Built These
- PR #15: Slow-Burn Curiosity
- PR #16: March 9 + PureTensor
- PR #17: Technical Changelog
- PR #20: Industry Commentary
4. **Import posts into scheduling tool** (buffer/Hootsuite/etc.)
5. **Set calendar for March 14 launch**
---
## What Samuel Can Do Locally (While Blocked on Auth)
1. ✅ Draft supplementary content:
- KubeCon day-of response templates (if unexpected narratives emerge)
- Post-KubeCon metrics/reflection post (template)
- Community response templates (FAQ for plugin questions)
2. ✅ Research emerging KubeCon narratives:
- Monitor Kubernetes news/blog for themes (storage, GPU, security trends)
- Prepare optional tie-in posts if news breaks that aligns with our narrative
3. ✅ Prepare CMO brief:
- High-level KubeCon strategy doc (target accounts, key hashtags, response protocols)
- Content-to-metric mapping (what each post is supposed to drive)
4. ✅ Monitor plugin repos for emergency content:
- If any plugin gets external attention/fork during March 13-27, draft celebratory post
- If issues or PRs spike, identify community moment to spotlight
---
## Questions for CMO
1. **Scheduling tool**: What platform are we using to schedule posts? (Buffer, Hootsuite, Twitter native scheduler, manual?)
- Affects how we format the final content export
2. **Post frequency**: The schedule above assumes daily/near-daily posts March 14-26. Acceptable?
- Can adjust cadence if different platform strategy preferred
3. **Reddit strategy**: Should the KubeCon Reddit post be cross-posted to other communities? (r/DevOps, r/SRE, etc.)
- Have opt-in templates ready if yes
4. **KubeCon day-of monitoring**: Should Samuel monitor #KubeCon hashtag during March 23-26 for response opportunities?
- Ready to draft real-time replies to conference conversations if needed
---
## Next Steps
1. **Resolve GitHub auth** (CMO/Engineering)
- Provide env var, GH_TOKEN, or gh CLI
- Samuel will push 8 branches immediately upon auth
2. **Approve rollout schedule** (CMO)
- Confirm March 14 launch date
- Approve Industry Commentary batch for immediate posting
- Flag any timing adjustments needed
3. **Set up scheduling tool** (CMO/Operations)
- Import KubeCon campaign posts
- Configure automation for daily posts March 21-27
4. **Samuel continues research** (in parallel)
- Draft supplementary content (community responses, FAQ)
- Monitor for emerging KubeCon themes
- Ready to create tactical day-of posts if needed
---
## Content Quality Highlights
**Industry Commentary Batch**: Establishes voice as operators who understand the gap between aspirational documentation and actual practices. Posts 1-3 are safe/immediately postable. Posts 4-5 are edgier but worth discussing. Posts 6-7 are evergreen.
**Why We Built These Batch**: Pain-point education that builds context before KubeCon. Each post has specific use case + why we built it. Strong candidate for pre-conference posting to establish credibility.
**KubeCon Campaign**: Rides #KubeCon conversation without forcing. Mix of self-deprecation ("1 star"), technical depth, and community positioning. Marquee post (March 26 ecosystem thread) should drive meaningful traffic.
---
## Git Branch Reference
```
d05b1f5 [social] batch: Industry commentary on Kubernetes ops culture
ba5a95e [content] technical changelog: March 9 releases and updates
f15f4c1 [social] batch: slow-burn curiosity post - K8s maturity gap awareness
b00be78 [social] batch: Why We Built These — problem-solution narrative for 6 plugins
f55dc48 [social] batch: March 9 releases + PureTensor community moment
0e07503 Draft KubeCon EU 2026 social posts — 6 posts for March 21-27
```
---
## Appendix: Full Content Titles
**Social Batches**
- Industry Commentary: observability theater, maintainer bottleneck, README as docs, consolidation trap, observability checkboxes, dependency hell, platform team reality
- Why We Built These: 6 posts (one per plugin, pain point + solution)
- March 9 + PureTensor: releases news + community moment
- Slow-Burn Curiosity: "The Dashboard You Don't Know You Need" (3 platform variants)
- KubeCon: 6 posts (teaser, 3 plugin spotlights, ecosystem thread, recap) + Reddit post
**Blog Posts**
- March 9 Releases Technical Changelog: versioned feature list + upgrade guide
- (Already deployed) Intro Blog Post
---
**Status**: Ready to ship on authorization. All content is quality-checked and voice-consistent. Awaiting GitHub auth resolution and CMO schedule approval.
**Last Updated**: March 13, 2026 | Samuel
@@ -0,0 +1,55 @@
---
title: "Six Headlamp Plugins Nobody Asked For"
date: 2026-03-07
author: Privileged Escalation
type: blog
status: draft
---
# Six Headlamp Plugins Nobody Asked For
There's a particular kind of optimism that only exists in open source. It's the belief that if you build something genuinely useful, put it on GitHub, list it on Artifact Hub, write actual documentation, and then wait — someone will eventually find it.
We're currently in the "wait" phase.
## What We Actually Built
Privileged Escalation makes [Headlamp](https://headlamp.dev/) plugins. If you don't know what Headlamp is: it's a CNCF-listed Kubernetes dashboard that was designed to be extended. If you don't know what Kubernetes is, this blog post is going to be a rough ride.
We have six plugins. Each one takes something you'd normally do with `kubectl`, a terminal, and quiet desperation, and puts it in a web UI that your teammates might actually use.
**[headlamp-polaris-plugin](https://github.com/privilegedescalation/headlamp-polaris-plugin)** — Surfaces Fairwinds Polaris audit results directly in Headlamp. Cluster score in the app bar, per-namespace breakdowns, exemption management from the UI instead of annotation YAML editing. Recently hit v0.6.0 with dark mode support, because apparently that's what it takes to be taken seriously in 2026.
**[headlamp-tns-csi-plugin](https://github.com/privilegedescalation/headlamp-tns-csi-plugin)** — TrueNAS CSI driver visibility and storage benchmarking via kbench. If you've ever wondered whether your NFS share is actually performing the way iX Systems promised, this is the plugin that tells you the uncomfortable truth.
**[headlamp-rook-plugin](https://github.com/privilegedescalation/headlamp-rook-plugin)** — Rook-Ceph cluster health, pool status, and CSI driver monitoring. For people who chose distributed storage and now live with the consequences.
**[headlamp-sealed-secrets-plugin](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin)** — Bitnami Sealed Secrets management with client-side RSA-OAEP and AES-256-GCM encryption. Your plaintext never leaves the browser. We're fairly proud of this one, which is why it hurts that it has zero stars.
**[headlamp-intel-gpu-plugin](https://github.com/privilegedescalation/headlamp-intel-gpu-plugin)** — Intel GPU device visibility and resource monitoring. For the subset of people running Intel GPUs in Kubernetes, which is a smaller group than Intel's marketing department would like.
**[headlamp-kube-vip-plugin](https://github.com/privilegedescalation/headlamp-kube-vip-plugin)** — kube-vip virtual IP and load balancer visibility. Because sometimes you just need to know if the VIP is actually where it's supposed to be.
## Why Headlamp Plugins
The Kubernetes dashboard space is... let's call it "stratified." There are expensive commercial options that do everything. There are free options that do almost nothing. And then there's Headlamp, which does a reasonable amount and lets you extend it.
We chose the extension path. Every plugin installs through Headlamp's native plugin system — no separate deployments, no new URLs to bookmark, no "please also install this sidecar that needs its own RBAC." You add a plugin and it appears in the sidebar. That's it.
This matters because the alternative is what most teams actually do: they `kubectl` their way through everything, pipe JSON through `jq`, and call it observability. It works. It's also miserable if you're trying to onboard anyone who doesn't have muscle memory for `kubectl get pods -n rook-ceph -o jsonpath='{.items[*].status.phase}'`.
## The Honest Part
We launched all six plugins in the same week. Combined star count across all repos: zero. Combined fork count: one, and we're not entirely sure it was intentional.
Our CI is sometimes in a state that could charitably be described as "aspirational." We filed a bug against ourselves about E2E tests that have never passed because we haven't set up the test infrastructure yet. We committed LICENSE badges to READMEs before we committed the actual LICENSE files.
This is normal. This is what early open source looks like before the narrative gets cleaned up. We'd rather be honest about it than pretend we emerged fully formed with 200 stars and a contributor covenant.
## What's Next
We're working on getting every plugin listed on Artifact Hub with proper metadata, fixing the CI pipelines that are currently failing for reasons ranging from "missing secrets" to "format check disagreements," and writing the kind of documentation that makes people confident enough to actually install something.
If you run Headlamp and any of these plugins sound useful, try one. If something breaks, file an issue. If it works and you like it, a star would be nice. We're not above admitting that.
All plugins are Apache-2.0 licensed. All repos are at [github.com/privilegedescalation](https://github.com/privilegedescalation).

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

-53
View File
@@ -1,53 +0,0 @@
<p align="center">
<img src="privilegedescalation-logo.jpg" alt="Privileged Escalation" width="300" />
</p>
<div align="center">
![GitHub Org stars](https://img.shields.io/github/stars/privilegedescalation)
![GitHub followers](https://img.shields.io/github/followers/privilegedescalation)
![License](https://img.shields.io/github/license/privilegedescalation/.github)
![Profile views](https://komarev.com/ghpvc/?username=privilegedescalation&color=brightgreen)
</div>
<h3 align="center">Headlamp plugins for the infrastructure you actually run.</h3>
<p align="center">
<a href="https://artifacthub.io/packages/search?org=privilegedescalation&kind=21">Artifact Hub</a>
·
<a href="https://headlamp.dev">Headlamp</a>
·
<a href="https://github.com/sponsors/privilegedescalation">Sponsor</a>
</p>
---
We build open source [Headlamp](https://headlamp.dev) plugins that bring deep visibility into Kubernetes storage, networking, GPU, and security subsystems — right inside your cluster dashboard.
## Our Plugins
| Plugin | What it does | Artifact Hub |
|--------|-------------|:---:|
| [headlamp-rook-plugin](https://github.com/privilegedescalation/headlamp-rook-plugin) | Rook-Ceph cluster health, pool status, and CSI driver monitoring | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-rook-plugin)](https://artifacthub.io/packages/headlamp/headlamp-rook-plugin/headlamp-rook-plugin) |
| [headlamp-tns-csi-plugin](https://github.com/privilegedescalation/headlamp-tns-csi-plugin) | TrueNAS CSI driver visibility and kbench storage benchmarking | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-tns-csi-plugin)](https://artifacthub.io/packages/headlamp/headlamp-tns-csi-plugin/headlamp-tns-csi-plugin) |
| [headlamp-sealed-secrets-plugin](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin) | Manage Bitnami Sealed Secrets with client-side encryption | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-sealed-secrets-plugin)](https://artifacthub.io/packages/headlamp/headlamp-sealed-secrets-plugin/headlamp-sealed-secrets-plugin) |
| [headlamp-polaris-plugin](https://github.com/privilegedescalation/headlamp-polaris-plugin) | Fairwinds Polaris security and best-practices auditing | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-polaris-plugin)](https://artifacthub.io/packages/headlamp/headlamp-polaris-plugin/headlamp-polaris-plugin) |
| [headlamp-intel-gpu-plugin](https://github.com/privilegedescalation/headlamp-intel-gpu-plugin) | Intel GPU device visibility and resource monitoring | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-intel-gpu-plugin)](https://artifacthub.io/packages/headlamp/headlamp-intel-gpu-plugin/headlamp-intel-gpu-plugin) |
| [headlamp-kube-vip-plugin](https://github.com/privilegedescalation/headlamp-kube-vip-plugin) | kube-vip virtual IP and load balancer visibility | [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/headlamp-kube-vip)](https://artifacthub.io/packages/headlamp/headlamp-kube-vip/headlamp-kube-vip) |
## Why Headlamp?
Headlamp is a CNCF-listed Kubernetes dashboard built for extensibility. Our plugins slot in natively — no separate UIs, no context switching. If you run Headlamp, you can add any of our plugins with a single command.
## Get Started
Every plugin is installable via the Headlamp plugin system. See individual repos for install instructions.
## Contributing
We welcome contributions, bug reports, and feature requests. Open an issue on any repo or start a discussion. All projects are licensed under Apache 2.0.
## Sponsor
If these plugins save your team time, consider [sponsoring our work](https://github.com/sponsors/privilegedescalation). Sponsorship funds go directly toward new plugin development and maintenance.
-33
View File
@@ -1,33 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"gitAuthor": "Renovate Bot <bot@renovateapp.com>",
"extends": ["config:recommended"],
"baseBranches": ["main"],
"schedule": ["every weekend"],
"prConcurrentLimit": 5,
"pinDigests": true,
"packageRules": [
{
"matchManagers": ["npm"],
"matchUpdateTypes": ["minor", "patch"],
"groupName": "npm minor and patch"
},
{
"matchManagers": ["npm"],
"matchUpdateTypes": ["major"],
"groupName": "npm major updates",
"automerge": false
},
{
"matchManagers": ["github-actions"],
"matchUpdateTypes": ["minor", "patch"],
"groupName": "github-actions minor and patch"
},
{
"matchManagers": ["github-actions"],
"matchUpdateTypes": ["major"],
"groupName": "github-actions major updates",
"automerge": false
}
]
}
-49
View File
@@ -1,49 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Reads a newline-separated list of changed files from stdin.
# Outputs "pipeline-a" or "pipeline-b" to stdout.
# Pipeline B: all files are infra-only (config, docs, workflows).
# Pipeline A: any non-infra file present.
detect_pipeline() {
local all_infra=true
while IFS= read -r file; do
[ -z "$file" ] && continue
local filename
local dir
filename=$(basename "$file")
dir=$(dirname "$file")
if [[ "$dir" == ".github" || "$dir" == .github/* ]] || \
[[ "$dir" == "infra" || "$dir" == infra/* ]] || \
[[ "$dir" == "org" || "$dir" == org/* ]] || \
[[ "$filename" == *.md ]] || \
[[ "$filename" == .eslintrc* ]] || \
[[ "$filename" == .prettierrc* ]] || \
[[ "$filename" == renovate.json* ]] || \
[[ "$filename" == .gitignore ]] || \
[[ "$filename" == .editorconfig ]] || \
[[ "$filename" == LICENSE ]] || \
[[ "$filename" == Dockerfile ]] || \
[[ "$filename" == docker-compose* ]] || \
[[ "$filename" == Makefile ]]; then
continue
else
all_infra=false
break
fi
done
if [ "$all_infra" = true ]; then
echo "pipeline-b"
else
echo "pipeline-a"
fi
}
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
detect_pipeline
fi
-145
View File
@@ -1,145 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-pipeline.sh"
PASS=0
FAIL=0
assert_eq() {
local test_name="$1" expected="$2" actual="$3"
if [ "$expected" = "$actual" ]; then
echo "PASS: $test_name"
PASS=$((PASS + 1))
else
echo "FAIL: $test_name (expected=$expected, actual=$actual)"
FAIL=$((FAIL + 1))
fi
}
run_detect() {
echo "$1" | detect_pipeline
}
# --- Pipeline B cases (infra-only) ---
assert_eq "single .github root file" "pipeline-b" \
"$(run_detect ".github/dependabot.yml")"
assert_eq ".github/workflows subdirectory" "pipeline-b" \
"$(run_detect ".github/workflows/ci.yaml")"
assert_eq "deeply nested .github path" "pipeline-b" \
"$(run_detect ".github/workflows/reusable/build.yaml")"
assert_eq "markdown file at root" "pipeline-b" \
"$(run_detect "README.md")"
assert_eq "markdown in subdirectory" "pipeline-b" \
"$(run_detect "docs/CONTRIBUTING.md")"
assert_eq "eslintrc config" "pipeline-b" \
"$(run_detect ".eslintrc.json")"
assert_eq "prettierrc config" "pipeline-b" \
"$(run_detect ".prettierrc.yaml")"
assert_eq "renovate config" "pipeline-b" \
"$(run_detect "renovate.json")"
assert_eq "renovate config5" "pipeline-b" \
"$(run_detect "renovate.json5")"
assert_eq "gitignore" "pipeline-b" \
"$(run_detect ".gitignore")"
assert_eq "editorconfig" "pipeline-b" \
"$(run_detect ".editorconfig")"
assert_eq "LICENSE" "pipeline-b" \
"$(run_detect "LICENSE")"
assert_eq "mixed infra files" "pipeline-b" \
"$(run_detect ".github/workflows/ci.yaml
README.md
.eslintrc.json
LICENSE")"
assert_eq "workflow + markdown combo" "pipeline-b" \
"$(run_detect ".github/workflows/detect-pr-pipeline.yaml
.github/workflows/README.md")"
assert_eq "infra root file" "pipeline-b" \
"$(run_detect "infra/helmrelease.yaml")"
assert_eq "infra nested file" "pipeline-b" \
"$(run_detect "infra/clusters/prod/kustomization.yaml")"
assert_eq "org root file" "pipeline-b" \
"$(run_detect "org/CODEOWNERS")"
assert_eq "org nested file" "pipeline-b" \
"$(run_detect "org/policies/branch-protection.json")"
assert_eq "Dockerfile" "pipeline-b" \
"$(run_detect "Dockerfile")"
assert_eq "docker-compose.yaml" "pipeline-b" \
"$(run_detect "docker-compose.yaml")"
assert_eq "docker-compose.override.yml" "pipeline-b" \
"$(run_detect "docker-compose.override.yml")"
assert_eq "Makefile" "pipeline-b" \
"$(run_detect "Makefile")"
assert_eq "mixed infra + org + workflow" "pipeline-b" \
"$(run_detect ".github/workflows/ci.yaml
infra/helmrelease.yaml
org/CODEOWNERS
README.md")"
# --- Pipeline A cases (has non-infra files) ---
assert_eq "plugin source file" "pipeline-a" \
"$(run_detect "headlamp-polaris-plugin/src/index.tsx")"
assert_eq "plugin package.json" "pipeline-a" \
"$(run_detect "headlamp-polaris-plugin/package.json")"
assert_eq "root source file" "pipeline-a" \
"$(run_detect "src/main.ts")"
assert_eq "mixed infra + code" "pipeline-a" \
"$(run_detect ".github/workflows/ci.yaml
headlamp-polaris-plugin/src/index.tsx
README.md")"
assert_eq "single non-infra file" "pipeline-a" \
"$(run_detect "server.js")"
assert_eq "plugin code + infra files" "pipeline-a" \
"$(run_detect "infra/helmrelease.yaml
org/CODEOWNERS
headlamp-polaris-plugin/src/index.tsx")"
# --- Edge cases ---
assert_eq "empty input" "pipeline-b" \
"$(run_detect "")"
assert_eq "root dot file (not in infra list)" "pipeline-a" \
"$(run_detect ".env")"
assert_eq ".github-like but not .github dir" "pipeline-a" \
"$(run_detect ".github-backup/config.yaml")"
# --- Summary ---
echo ""
echo "Results: $PASS passed, $FAIL failed"
if [ "$FAIL" -gt 0 ]; then
exit 1
fi
+85
View File
@@ -0,0 +1,85 @@
# Social Media Batch - 2026-03-07
## Strategic Summary
First-ever social batch for Privileged Escalation. The org has 6 Headlamp plugins across storage, security, and infrastructure -- all freshly released, all at zero stars. The play here is name recognition and curiosity: make people encounter "Privileged Escalation" in their feed and wonder what it is before they click. Leading with the sealed-secrets plugin (client-side crypto angle) and the absurdity of launching 6 plugins to zero fanfare.
---
## 1. Ready to Post
### Post 1
**Platform**: Twitter/X
**Post**:
We shipped 6 Kubernetes Headlamp plugins and nobody noticed.
Storage benchmarking, Rook-Ceph visibility, Polaris auditing, Sealed Secrets with actual client-side encryption, Intel GPU monitoring, and kube-vip dashboards.
Zero stars across the board. We are crushing it.
github.com/privilegedescalation
**CMO Note**: Self-deprecating launch acknowledgment. The honesty about zero stars is the hook -- it reads as human, not corporate. Links to the org for curious clicks.
---
### Post 2
**Platform**: Bluesky
**Post**:
the sealed secrets headlamp plugin does client-side RSA-OAEP + AES-256-GCM encryption so your plaintext never leaves the browser.
someone forked it last month. we have our first user. or our first person who accidentally clicked fork. either way, we are celebrating.
**CMO Note**: Technical specificity makes it credible. The fork joke (sm-moshi, Feb 22) is real and plays well on Bluesky's irony-friendly audience. Seeds curiosity about what Headlamp plugins are.
---
### Post 3
**Platform**: Mastodon
**Post**:
Genuine question for the fediverse: if you have 6 open source projects and zero stars on any of them, are you a software company or just a guy with a lot of repos?
Asking for a friend. The friend is github.com/privilegedescalation.
**CMO Note**: Mastodon audience appreciates self-aware humor. This is pure slow-burn -- raises the question of what Privileged Escalation is without explaining it. The link is there for anyone curious enough to click.
---
## 2. Risky but Worth Discussing
### Post 4
**Platform**: Twitter/X
**Post**:
Every Kubernetes UI either costs money or looks like it was designed during a mass layoff event.
We've been building Headlamp plugins that make the free one actually useful. Rook-Ceph dashboards, Polaris auditing, storage benchmarks -- the stuff you duct-tape together with kubectl and regret.
github.com/privilegedescalation
**CMO Note**: Mildly spicy take on the K8s UI landscape. Does not name competitors directly but the implication is clear. Could rub Lens/Rancher people the wrong way. Worth discussing tone.
---
## 3. Backlog (Evergreen)
### Post 5
**Platform**: LinkedIn
**Post**:
We just audited our own GitHub repos and found that 4 out of 6 were missing LICENSE files.
They all had Apache-2.0 badges in the README. The actual license text? Not present. Technically, anyone using our code was operating on vibes and good faith.
Fixed now. But if your open source project has a license badge and no LICENSE file, maybe go check. We'll wait.
**CMO Note**: Honest product personality at work. Admitting a real flaw (that we just fixed) builds trust and is genuinely useful advice. LinkedIn audience will share practical open source governance content.
---
### Post 6
**Platform**: Twitter/X
**Post**:
TIL "Privileged Escalation" as a GitHub org name gets flagged by approximately zero security scanners.
We checked.
**CMO Note**: Pure name recognition play. The org name is inherently memorable and slightly provocative -- leaning into that. Short enough for easy engagement.