mirror of
https://github.com/getcargohq/cargo-skills.git
synced 2026-09-14 19:17:15 +08:00
Point the CDK skill at cdk add, and stop documenting a template flag (#121)
The cookbook guidance said there was no copy tool and the agent had to place the code itself. `cdk add cookbook/<slug>` is that tool now, so the skill says what it does, where it writes, and — the part an agent gets wrong — that the cookbook's own procedure has to be picked up at its Adapt section, because its opening steps assume you found the folder on GitHub and still have to place it. The command reference documented `--template <blank|full>` and `--list-templates` for `cdk init`. Neither flag exists: the scaffold never varies and a worked example comes from a cookbook. It also had no row for `add` or `cookbook` at all, which is the reference an agent reads to decide what to run. Fixed, along with the two recipes and the example that invoked `--template full`. Refreshes the cookbook snapshot, which had gone stale at two cookbooks while the catalog grew to three — `crm-enrichment` was missing from the menu. Regenerates llms.txt and the skill's metadata snapshot, both CI-gated. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -25,6 +25,37 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"slug": "crm-enrichment",
|
||||
"kind": "cookbook",
|
||||
"outcome": "Keep CRM accounts filled and refresh them when they go stale: a deployed play that fills approved blank firmographics from LinkedIn and re-enrolls a record after six months.",
|
||||
"state": "to-be-approved",
|
||||
"chain": 3,
|
||||
"requires": [],
|
||||
"hasSkill": true,
|
||||
"variations": [
|
||||
{
|
||||
"id": "crm",
|
||||
"when": "The consumer uses Salesforce or Attio instead of HubSpot",
|
||||
"trade": "Live generated types must be rechecked; a guessed flag writes or no-ops silently"
|
||||
},
|
||||
{
|
||||
"id": "selected_fields",
|
||||
"when": "The approved contract differs from the starting recommendation",
|
||||
"trade": "Each added field expands mapping, type-review, and the \"already filled\" filter"
|
||||
},
|
||||
{
|
||||
"id": "eligibility",
|
||||
"when": "Only a governed subset should be enriched",
|
||||
"trade": "Narrower scope reduces coverage and paid calls"
|
||||
},
|
||||
{
|
||||
"id": "approved_refresh_behavior",
|
||||
"when": "Populated fields must be refreshed after explicit approval",
|
||||
"trade": "Refresh can overwrite CRM-authoritative values if the preview and the write disagree"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"slug": "tam-building",
|
||||
"kind": "cookbook",
|
||||
|
||||
@@ -93,16 +93,22 @@ function render(examples: Cookbook[]): string {
|
||||
L.push("jobs as the one-off skills there, as a deployed pipeline that keeps producing the result.");
|
||||
L.push("");
|
||||
L.push("**Every folder is self-contained** (its own models, connectors and folders; no shared");
|
||||
L.push("foundation, no requires graph). The agent installing one copies it into the project as a");
|
||||
L.push("sibling of what is there, reconciles it with what is already declared (an existing accounts");
|
||||
L.push("model, an existing CRM connector), adapts it, plans, deploys on a yes, and walks its `Done");
|
||||
L.push("when`. The code is a worked example, not a template to fill in.");
|
||||
L.push("foundation, no requires graph). `cdk add` copies one into the project; the agent then");
|
||||
L.push("reconciles it with what is already declared (an existing accounts model, an existing CRM");
|
||||
L.push("connector), adapts it in place, plans, deploys on a yes, and walks its `Done when`. The");
|
||||
L.push("code is a worked example, not a template to fill in — and not something to regenerate");
|
||||
L.push("from the skill's prose.");
|
||||
L.push("");
|
||||
L.push("```sh");
|
||||
L.push(`npx skills add ${REPO}/<slug> # then say what you want; the skill carries its own procedure`);
|
||||
L.push("cargo-ai cdk init <dir> --template blank # only if there is no CDK project yet: the shell comes from the CLI");
|
||||
L.push("cargo-ai cdk add cookbook/<slug> # inside a CDK project: this is the copy step");
|
||||
L.push("cargo-ai cdk init <dir> --cookbook <slug> # no project yet: scaffold and install together");
|
||||
L.push(`npx skills add ${REPO}/<slug> # the procedure on its own, without the CDK resources`);
|
||||
L.push("```");
|
||||
L.push("");
|
||||
L.push("After either `cdk` command the files are in `infra/<slug>/` and `.claude/skills/<slug>/`.");
|
||||
L.push("Start the skill at its Adapt section: its earlier steps assume you found the folder in");
|
||||
L.push("gtm-skills and still have to place it.");
|
||||
L.push("");
|
||||
L.push("## With a skill");
|
||||
L.push("");
|
||||
L.push("| Skill | Deploys | State |");
|
||||
@@ -131,8 +137,8 @@ function render(examples: Cookbook[]): string {
|
||||
L.push("");
|
||||
L.push("**Never `cargo-ai cdk init --force` into a directory that is not empty.** It replaces the");
|
||||
L.push("project's `package.json` and reverts adapted code while `cargo.state.json` survives, so the");
|
||||
L.push("next plan diffs a live workspace against code nobody wrote. Copy the skill folder in as a");
|
||||
L.push("sibling instead; that is what its own procedure says.");
|
||||
L.push("next plan diffs a live workspace against code nobody wrote. Run `cdk add cookbook/<slug>`");
|
||||
L.push("in the project that is already there; it skips every file it would otherwise overwrite.");
|
||||
L.push("");
|
||||
return L.join("\n");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ jobs:
|
||||
mode: scan
|
||||
format: markdown
|
||||
output: scanner-report.md
|
||||
config: .plugin-scanner.toml
|
||||
min_score: 80
|
||||
fail_on_severity: high
|
||||
# No `pull-requests: write` above, so the comment would fail anyway.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# Plugin scanner baseline suppressions
|
||||
# https://hol.org/docs/libraries/ai-plugin-scanner/plugin-scanner/policies-and-output/
|
||||
#
|
||||
# False positives from cisco-ai-skill-scanner >= 2.0.14 flagging standard
|
||||
# Unicode typography as "obfuscated prompt-injection".
|
||||
#
|
||||
# The flagged characters are legitimate documentation formatting:
|
||||
# - → (U+2192) — arrow notation in "5→40/day"
|
||||
# - — (U+2014) — standard em dash punctuation
|
||||
#
|
||||
# Generated: 2026-09-02
|
||||
|
||||
# cargo-observability/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-observability/SKILL.md
|
||||
|
||||
# cargo-gtm/SKILL.md — unicode-confusable false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-gtm/SKILL.md
|
||||
|
||||
# cargo-gtm/provider-playbooks/brightData.md — unicode-confusable false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-gtm/provider-playbooks/brightData.md
|
||||
|
||||
# cargo-mailbox-management/SKILL.md — unicode-normalization false positive (5→40)
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-mailbox-management/SKILL.md
|
||||
|
||||
# cargo/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo/SKILL.md
|
||||
|
||||
# cargo/references/prerequisites.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo/references/prerequisites.md
|
||||
|
||||
# cargo-storage/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-storage/SKILL.md
|
||||
|
||||
# cargo-storage/references/examples/ingest-webhook.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-storage/references/examples/ingest-webhook.md
|
||||
|
||||
# cargo-billing/SKILL.md — unicode-confusable false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-billing/SKILL.md
|
||||
|
||||
# cargo-cdk/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-cdk/SKILL.md
|
||||
|
||||
# cargo-diagnostics/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-diagnostics/SKILL.md
|
||||
|
||||
# cargo-context/SKILL.md — unicode-normalization false positive
|
||||
OBFUSCATED_PROMPT_INJECTION:cargo-context/SKILL.md
|
||||
@@ -0,0 +1,15 @@
|
||||
# Plugin scanner configuration
|
||||
# https://hol.org/docs/libraries/ai-plugin-scanner/plugin-scanner/policies-and-output/
|
||||
#
|
||||
# This baseline suppresses false positives from cisco-ai-skill-scanner >= 2.0.14
|
||||
# which incorrectly flags standard Unicode typography (em dashes, arrows) as
|
||||
# "obfuscated prompt-injection instructions".
|
||||
#
|
||||
# The flagged characters are:
|
||||
# - → (rightwards arrow, U+2192) — used in "5→40/day" ramp notation
|
||||
# - — (em dash, U+2014) — standard typographic punctuation
|
||||
#
|
||||
# These are normal documentation formatting, not obfuscation attempts.
|
||||
|
||||
[scanner]
|
||||
baseline_file = ".plugin-scanner-baseline.txt"
|
||||
+21
-12
@@ -153,21 +153,30 @@ before authoring a common GTM outcome from scratch. It is generated from gtm-ski
|
||||
`catalog.json`, so it cannot drift.
|
||||
|
||||
**A cookbook is a worked example, not a template to fill in.** Each one declares in its `SKILL.md` what may be reshaped, what must hold or it stops
|
||||
working, and what has to be answered either way, and it carries its own procedure:
|
||||
look at the repo, `cargo-ai cdk init --template blank` if there is no CDK project yet,
|
||||
copy the folder in as a sibling and reconcile it with what is already declared, adapt,
|
||||
plan and stop, deploy on a yes, walk its `Done when`. There is no scaffolder or copy
|
||||
tool in the middle: **you place the code**, because you can see the project and a tool
|
||||
cannot.
|
||||
working, and what has to be answered either way, and it carries its own procedure.
|
||||
`cdk add` is the copy step in that procedure:
|
||||
|
||||
```sh
|
||||
npx skills add getcargohq/gtm-skills/tam-building # then: "keep our TAM current"
|
||||
cargo-ai cdk init my-project --template blank # only if there is no CDK project yet
|
||||
cargo-ai cdk add cookbook/tam-building # inside a CDK project
|
||||
cargo-ai cdk init my-project --cookbook tam-building # no project yet: both at once
|
||||
```
|
||||
|
||||
**If you are mid-task and the skill is not in this session**, run the `skills add`
|
||||
above and read `.agents/skills/<slug>/SKILL.md` directly; no reload needed. To read
|
||||
one without installing, `npx skills use getcargohq/gtm-skills@<slug>` prints it.
|
||||
That writes the resources to `infra/tam-building/` and the procedure to
|
||||
`.claude/skills/tam-building/`, skipping any file it would overwrite. **Then start the
|
||||
skill at its Adapt section** — its opening steps are written for someone who found the
|
||||
folder on GitHub and still has to place it, so following them from the top scaffolds a
|
||||
second project and copies the folder in again.
|
||||
|
||||
What is left after the copy is the part only you can do: reconcile it with what is
|
||||
already declared, adapt the copied files **in place** to the project's real shape (do not
|
||||
regenerate them from the skill's prose — the safety lives in the TypeScript), plan and
|
||||
stop, deploy on a yes, walk its `Done when`.
|
||||
|
||||
**If you are mid-task and the skill is not in this session**, `npx skills add
|
||||
getcargohq/gtm-skills/<slug>` fetches the procedure alone and you can read
|
||||
`.agents/skills/<slug>/SKILL.md` directly; no reload needed. To read one without
|
||||
installing, `npx skills use getcargohq/gtm-skills@<slug>` prints it. Neither brings the
|
||||
CDK resources — for those you still want `cdk add`.
|
||||
|
||||
**Routing rule: one-off versus standing.** A user who wants the list today wants
|
||||
`cargo-gtm` (or gtm-skills' one-off `build-tam-list`); a user who wants a pipeline
|
||||
@@ -188,7 +197,7 @@ acceptance test, and always review `cargo-ai cdk plan` before deploying.
|
||||
|
||||
| Recipe | Use when… |
|
||||
|---|---|
|
||||
| [`recipes/scaffold-a-workspace.md`](recipes/scaffold-a-workspace.md) | Standing up a new workspace from scratch (`init --template full` → types → plan → deploy). |
|
||||
| [`recipes/scaffold-a-workspace.md`](recipes/scaffold-a-workspace.md) | Standing up a new workspace from scratch (`init` → types → plan → deploy). |
|
||||
| [`recipes/add-connector-and-model.md`](recipes/add-connector-and-model.md) | Adding a data source + a model sourced from it, wired by handle. |
|
||||
| [`recipes/build-an-agent.md`](recipes/build-an-agent.md) | Composing a model + tool + agent (with `uses` / `models` / `tools`) and deploying. |
|
||||
| [`recipes/migrate-existing-workspace.md`](recipes/migrate-existing-workspace.md) | Bringing an already-live workspace under CDK management via `cdk import`. |
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
# Recipe: scaffold a workspace from scratch
|
||||
|
||||
**Use when** the user wants to stand up a new Cargo workspace as code — from a
|
||||
template, reproducibly. Follow these steps as your execution plan.
|
||||
**Use when** the user wants to stand up a new Cargo workspace as code,
|
||||
reproducibly. Follow these steps as your execution plan.
|
||||
|
||||
## 1. Scaffold from a template
|
||||
## 1. Scaffold
|
||||
|
||||
```bash
|
||||
cargo-ai cdk init my-workspace # 'blank' (minimal) — the default
|
||||
cargo-ai cdk init my-workspace --template full # every resource type, wired up
|
||||
cargo-ai cdk init --list-templates # see all templates
|
||||
cargo-ai cdk init my-workspace # the repo, empty
|
||||
cargo-ai cdk init my-workspace --cookbook tam-building # the repo plus a worked example
|
||||
```
|
||||
|
||||
Use `--template full` when the user wants a worked example spanning connectors,
|
||||
models, plays, tools, agents, MCP, context, files, workers, and apps; `blank` when
|
||||
they want to start empty.
|
||||
The scaffold itself never varies — it is one GTM repo from
|
||||
`getcargohq/cargo-manifest`, with the CDK project in `infra/`. What varies is
|
||||
whether a cookbook is layered on top, so reach for `--cookbook <slug>` when the
|
||||
user wants a working pipeline to adapt rather than an empty project.
|
||||
`cargo-ai cdk cookbook list` names them; see
|
||||
[`references/cookbooks.md`](../references/cookbooks.md).
|
||||
|
||||
## 2. Install and authenticate
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ All subcommands accept `--dir <path>` (the project root, default `.`) and `--jso
|
||||
|
||||
| Command | What it does |
|
||||
|---|---|
|
||||
| `cargo-ai cdk init <directory>` | Scaffold a project from a template. `--template <blank\|full>` (default `blank`), `--list-templates`. |
|
||||
| `cargo-ai cdk init <directory>` | Scaffold a GTM repo from `getcargohq/cargo-manifest`, with the CDK project in `infra/`. `--name <name>`, `--cookbook <slug>` (install a cookbook into the new project), `--force` (write into a non-empty directory). There is no template flag: the scaffold never varies, and what varies is the cookbook layered on top. |
|
||||
| `cargo-ai cdk add cookbook/<slug>` | Copy a worked example into this project — `infra/<slug>/` plus its procedure under the skills directories. `--overwrite` (replace existing files; default skips them), `--yes`. Omit the address to choose interactively. |
|
||||
| `cargo-ai cdk add connector/<integration>` | Authorize a connector in the browser and write its `defineConnector`. `--connector-uuid <uuid>` adopts one already created there. |
|
||||
| `cargo-ai cdk cookbook list\|search\|view` | Browse the cookbooks `add` installs — `view <slug>` shows what one deploys, what it will ask you for, and its declared adaptations. |
|
||||
| `cargo-ai cdk types` | Generate per-workspace types into `.cargo-ai/` for typed config. |
|
||||
| `cargo-ai cdk plan` | Offline: compile the graph and diff against `cargo.state.json`. No API calls. |
|
||||
| `cargo-ai cdk deploy` | Create/update resources in dependency order; write state. Prompts unless `--yes`. |
|
||||
@@ -40,7 +43,8 @@ All subcommands accept `--dir <path>` (the project root, default `.`) and `--jso
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
cargo-ai cdk init acme --template full # scaffold
|
||||
cargo-ai cdk init acme # scaffold
|
||||
cargo-ai cdk add cookbook/tam-building --dir acme # layer a worked example on
|
||||
cargo-ai cdk types --dir acme # type config
|
||||
cargo-ai cdk plan --dir acme # preview
|
||||
cargo-ai cdk deploy --dir acme --yes # apply (non-interactive)
|
||||
|
||||
@@ -6,21 +6,28 @@ Skills in [`getcargohq/gtm-skills`](https://github.com/getcargohq/gtm-skills) th
|
||||
jobs as the one-off skills there, as a deployed pipeline that keeps producing the result.
|
||||
|
||||
**Every folder is self-contained** (its own models, connectors and folders; no shared
|
||||
foundation, no requires graph). The agent installing one copies it into the project as a
|
||||
sibling of what is there, reconciles it with what is already declared (an existing accounts
|
||||
model, an existing CRM connector), adapts it, plans, deploys on a yes, and walks its `Done
|
||||
when`. The code is a worked example, not a template to fill in.
|
||||
foundation, no requires graph). `cdk add` copies one into the project; the agent then
|
||||
reconciles it with what is already declared (an existing accounts model, an existing CRM
|
||||
connector), adapts it in place, plans, deploys on a yes, and walks its `Done when`. The
|
||||
code is a worked example, not a template to fill in — and not something to regenerate
|
||||
from the skill's prose.
|
||||
|
||||
```sh
|
||||
npx skills add getcargohq/gtm-skills/<slug> # then say what you want; the skill carries its own procedure
|
||||
cargo-ai cdk init <dir> --template blank # only if there is no CDK project yet: the shell comes from the CLI
|
||||
cargo-ai cdk add cookbook/<slug> # inside a CDK project: this is the copy step
|
||||
cargo-ai cdk init <dir> --cookbook <slug> # no project yet: scaffold and install together
|
||||
npx skills add getcargohq/gtm-skills/<slug> # the procedure on its own, without the CDK resources
|
||||
```
|
||||
|
||||
After either `cdk` command the files are in `infra/<slug>/` and `.claude/skills/<slug>/`.
|
||||
Start the skill at its Adapt section: its earlier steps assume you found the folder in
|
||||
gtm-skills and still have to place it.
|
||||
|
||||
## With a skill
|
||||
|
||||
| Skill | Deploys | State |
|
||||
| --- | --- | --- |
|
||||
| `account-scoring` | Keep every account scored and tiered against your written ICP by a deployed agent that re-scores as accounts arrive and as the ICP changes, writing the rationale back to the CRM. | to-be-approved |
|
||||
| `crm-enrichment` | Keep CRM accounts filled and refresh them when they go stale: a deployed play that fills approved blank firmographics from LinkedIn and re-enrolls a record after six months. | to-be-approved |
|
||||
| `tam-building` | Stand up your account universe as a deployed pipeline: a Sales Navigator company search split past the 1,000 extraction cap, resolved to real domains, deduped into a shared accounts model. | to-be-approved |
|
||||
|
||||
## When one does not fit as written
|
||||
@@ -33,6 +40,13 @@ Declared adaptations, not forks. Reach for one before concluding a skill is the
|
||||
- `skip-crm-roundtrip` — You want the score on the model directly and do not need it visible in the CRM. Costs: Reps lose the score and rationale where they actually work. The native's input is untyped, so confirm the field shape on the first run.
|
||||
- `no-crm-at-all` — You have no CRM, or you do not want to hand this skill a CRM credential. Costs: Every other CRM-dependent skill you install later brings a CRM connector of its own; reuse one.
|
||||
|
||||
**`crm-enrichment`**
|
||||
|
||||
- `crm` — The consumer uses Salesforce or Attio instead of HubSpot. Costs: Live generated types must be rechecked; a guessed flag writes or no-ops silently.
|
||||
- `selected_fields` — The approved contract differs from the starting recommendation. Costs: Each added field expands mapping, type-review, and the "already filled" filter.
|
||||
- `eligibility` — Only a governed subset should be enriched. Costs: Narrower scope reduces coverage and paid calls.
|
||||
- `approved_refresh_behavior` — Populated fields must be refreshed after explicit approval. Costs: Refresh can overwrite CRM-authoritative values if the preview and the write disagree.
|
||||
|
||||
**`tam-building`**
|
||||
|
||||
- `non-linkedin-source` — You do not want to source from LinkedIn at all, or Sales Nav does not cover your market. Costs: You lose the Sales Nav facet taxonomy that makes the split tactic mechanical, and the splitting has to be redesigned around the new source's own limits.
|
||||
@@ -48,5 +62,5 @@ result is meant to keep arriving.
|
||||
|
||||
**Never `cargo-ai cdk init --force` into a directory that is not empty.** It replaces the
|
||||
project's `package.json` and reverts adapted code while `cargo.state.json` survives, so the
|
||||
next plan diffs a live workspace against code nobody wrote. Copy the skill folder in as a
|
||||
sibling instead; that is what its own procedure says.
|
||||
next plan diffs a live workspace against code nobody wrote. Run `cdk add cookbook/<slug>`
|
||||
in the project that is already there; it skips every file it would otherwise overwrite.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# Example: a full GTM workspace end-to-end
|
||||
|
||||
This walks the `full` template (`cargo-ai cdk init <dir> --template full`) — a
|
||||
complete, runnable Cargo workspace defined in code that exercises every resource
|
||||
type and wires them by **handle**.
|
||||
This walks a complete, runnable Cargo workspace defined in code that exercises
|
||||
every resource type and wires them by **handle**. It is a reading example, not
|
||||
something a command scaffolds: `cargo-ai cdk init` produces one repo shape, and a
|
||||
worked pipeline comes from `cargo-ai cdk add cookbook/<slug>`.
|
||||
|
||||
## The graph
|
||||
|
||||
|
||||
@@ -74,5 +74,5 @@
|
||||
"title": "Troubleshooting"
|
||||
}
|
||||
],
|
||||
"contentHash": "9bab53eda7c82d2c830dfb5ed20f8eee3ca499e86bb8cb7a01c38a95664e121f"
|
||||
"contentHash": "155934e2efdd7b6775c7339c8c991ac4712152f186439bbab975da98d3efdebf"
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ Step-by-step playbooks for a specific job. An agent loads the parent skill, then
|
||||
- [build-an-agent](https://github.com/getcargohq/cargo-skills/blob/main/cargo-cdk/recipes/build-an-agent.md): Use when the user wants an AI agent with a data model, a tool, and an LLM
|
||||
- [deploy-from-ci](https://github.com/getcargohq/cargo-skills/blob/main/cargo-cdk/recipes/deploy-from-ci.md): Use when the user wants cargo-ai cdk deploy to run non-interactively — on
|
||||
- [migrate-existing-workspace](https://github.com/getcargohq/cargo-skills/blob/main/cargo-cdk/recipes/migrate-existing-workspace.md): Use when a workspace already has live resources (built in the UI or the
|
||||
- [scaffold-a-workspace](https://github.com/getcargohq/cargo-skills/blob/main/cargo-cdk/recipes/scaffold-a-workspace.md): Use when the user wants to stand up a new Cargo workspace as code — from a
|
||||
- [scaffold-a-workspace](https://github.com/getcargohq/cargo-skills/blob/main/cargo-cdk/recipes/scaffold-a-workspace.md): Use when the user wants to stand up a new Cargo workspace as code,
|
||||
|
||||
## Provider playbooks
|
||||
|
||||
|
||||
Reference in New Issue
Block a user