Feedback Feature: Operator Setup
Overview
The feedback feature embeds GitHub issue tracking directly into the stylo.bot site. Visitors can submit feedback, which is written as issues to the scottgal/stylobot GitHub repository. The feedback form adapts based on the visitor's bot verdict (read from the gateway-forwarded X-Bot-Detection-* headers): human visitors see the full form; high-confidence bot traffic is gated server-side by StyloBotFeedbackFormPolicy.
The feature is powered by StyloIssues: a host-agnostic GitHub-backed issue tracker. The site wires AddStyloIssues (DI), MapStyloIssues (write endpoints), and a FeedbackController (read pages at GET /feedback and GET /feedback/{number:int}).
Required Secrets
None of the following values are committed to source control. Provide them via user-secrets (development) or environment variables (production).
Development: user-secrets
dotnet user-secrets --project src/Stylobot.Website set "StyloIssues:PersonalAccessToken" "<a fine-grained PAT with issues read/write on scottgal/stylobot>"
dotnet user-secrets --project src/Stylobot.Website set "StyloIssues:MarkerKey" "<a random 32+ char HMAC key>"
dotnet user-secrets --project src/Stylobot.Website set "StyloIssues:WebhookSecret" "<the GitHub App webhook secret, if wiring inbound>"
Production: environment variables
Set the equivalent environment variables, using double-underscore as the section separator:
StyloIssues__PersonalAccessToken=<PAT>
StyloIssues__MarkerKey=<HMAC key>
StyloIssues__WebhookSecret=<webhook secret>
These map to StyloIssues:PersonalAccessToken, StyloIssues:MarkerKey, and StyloIssues:WebhookSecret in appsettings, which Program.cs reads at startup via AddStyloIssues(o => ...).
GitHub PAT
Create a fine-grained personal access token at: https://github.com/settings/tokens?type=beta
Required permissions on the scottgal/stylobot repository:
- Issues: Read and Write
No other permissions are needed. The PAT is used only for creating and reading issues; it is never exposed to the browser.
HMAC Marker Key
StyloIssues:MarkerKey is a server-side secret used to sign the zero-PII visitor marker embedded in issue bodies. Generate with any cryptographically random 32+ byte source, for example:
openssl rand -base64 32
The marker lets the site link a returning visitor to their own prior submissions without storing any PII.
Webhook Secret (optional)
StyloIssues:WebhookSecret is only needed if you wire GitHub's inbound webhook to POST /feedback/webhook for real-time issue sync. If not configured, the site reads issues on-demand from the GitHub API and the webhook endpoint is a no-op.
Gateway Posture Requirement
The gateway must not block or refuse visitor traffic to /feedback before the site can respond. Two acceptable postures:
Observe-only (recommended for the calibration window): Set
BlockDetectedBots = falseat the gateway. All traffic reaches the site;StyloBotFeedbackFormPolicyuses the gateway-forwarded verdict headers to gate the form server-side. This is the default shipping posture.Logonly policy on
/feedback: Apply alogonlyaction policy scoped to/feedbackpaths via the policy-stack editor. Detection still runs and signals are recorded; no visitor is refused.
Do not apply a blanket block policy to /feedback: the form's bot-verdict gate runs inside the site (via StyloBotFeedbackFormPolicy), so blocking at the gateway would prevent the site from ever rendering the page to determine whether the visitor qualifies.
Verdict Headers
The site reads the bot verdict from the X-Bot-Detection-* request headers the gateway injects on the forwarded request before it reaches the site (the constants in StyloBotEdgeHeaderNames). These are the upstream-forwarded request headers, distinct from the X-StyloBot-* response headers the gateway returns to the client:
X-Bot-Detection-Probability: bot probability (0.0-1.0)X-Bot-Detection-RiskBand: theRiskBandenum name (PascalCase), one ofUnknown,VeryLow,Low,Elevated,Medium,High,VeryHigh,VerifiedX-Bot-Detection-BotType: bot classification (e.g.Human,AiScraper)X-Bot-Detection-BotName: display name assigned by the gatewayX-Bot-Detection-ThreatBand: threat band for the request
StyloBotFeedbackFormPolicy maps the risk band to a form state: High/VeryHigh render the Bare form (submit hidden), Medium/Elevated render ChallengeGated, and everything else (VeryLow, Low, Verified, Unknown, or an absent header) fails open to the Full form. Friendly bot types (VerifiedBot, SearchEngine, SocialMediaBot, Internal) always get the Full form regardless of risk band.
These headers are read by WebsiteCurrentUser (to build the ICurrentUser record passed to StyloIssues) and by StyloBotFeedbackFormPolicy (to decide whether the form should render). No gateway change is required; the gateway already injects these headers on every forwarded request.
Deferred
The following items are planned but not yet implemented:
- Held-for-review moderation queue (high-threat submissions held before publish).
- GitHub account-link for named attribution (OAuth flow, separate task).
- Inbound webhook sync wiring (real-time issue state refresh via
POST /feedback/webhook).