StyloBot-Release-Serien-:-Behaviour--Aware TypeScript UI
Bot-Erkennung sollte nicht bei allow ./ .block ?. . Dieser Beitrag zeigt, wie StyloBot' .s Klassifikation Ergebnis wird Anwendung Logik in TypeScript . : . Server Middleware für Express und Fastify . , . Schablone Helfer für Lenker .
Das
@stylobot/coreund@stylobot/nodenpm-Pakete werden in Kürze veröffentlicht Die Schnipsel unten beschreiben die Oberfläche, die sie aussetzen werden
StyloBot Release Series
- Verhalten nicht IdentitätWarum StyloBot die Kunden verhaltensmäßig modelliert
- Verhalten Bewusst WERDENDie Server-Oberfläche von -, die für Anwendungen von . oder NET bestimmt ist
- Ungebundenes Wachstum in langen --Diensten finden und behebenDie Zuverlässigkeitsdisziplin, die den Motor in der Produktion langweilig hält
- Verhalten--Bewusstsein TypScript UIDieser Artikel
- Die Sidecar-ArchitekturWie der Detektions-Engine mit Nicht--.-NET-Stacks verbunden wird
- Schneller lernenDas adaptive Lernsystem (MSK) und der Urteilscache
- Testen der Sache, die Won-' sitt StillEine BDF-Datei treibt Regression an.
- StyloExtrahieren Sie einen lokalen HTML zu Markdown KonverterDie HTML-Markdown-Schicht, die sich mit dem Detektor verbindet, hat den Walker Bug lucidVIEW gefangen und die Hundefutterschleife, die es ehrlich machte.
StyloBot-'s Detektionsmaschine ist geschrieben in ASP...NET Core...:... ein hochleistungsfähiges Rahmenwerk mit hervorragenden async Primitives...MSC4. sub.MSC5.millisekunden heiß-.path Latency, und zwanzig Jahre Produktionsstamm dahinter Das TypeScript SDK ist die Oberfläche, die den Motor bringt hot messK9s Ausgabe in Node messk10.js Anwendungen und Browser ohne entweder etwas darüber zu wissen, was unter dem passiert ist, .. (. Die heißen -.path-Latency kommt aus dem adaptiven Lernsystem abgedeckt in Schneller lernenSobald ein Fingerabdruck mit genügend Vertrauen gesehen wurde, überspringt der Urteilscache die vollständige Detektor-Pipeline und antwortet in Mikrosekunden.
Einleitung
Die meisten Bot-Erkennung im TypeScript Ökosystem gibt Ihnen eines von zwei Dingen .: , ein Browser-Fingerabdruck, der Ihnen sagt, ob die Kunde sieht automatisiert aus oder ein Regex über dem User-String, der nur die Bots fängt, die sich selbst ankündigen
Auch bei der Applikationsschicht nicht nützlich
Abbott läuft im Browser und hat keine Ansicht von Anfrage-Headern., , TLS Fingerabdrucke ,, , Sitzungsverhalten oder IP Reputation , . , Ein kopfloses Chrom und ein Googlebot aussehen identisch mit ihm ,. , Pure UA Matching Pakete , ( ,is-bot, isbot)-Schnappen Sie nur, was sich in zu werden gefangen entscheidet ..-Netzwerk .--Schicht-Produkte ?(-Cloudflare Bot Management - ,-DatenDome-)-Block am Rand, aber nicht an der Applikationsschicht personalisieren können . .-Sie lernen eine Anfrage wurde blockiert ,-Schneid nie, dass eine Anfrage, die Ihre App erreicht hatte eine Wahrscheinlichkeit und ein Medium Risikoband . ,-, so dass Ihre Checkout-Seite könnte gezeigt haben, einen Reibungsschritt und Ihre Analysen könnten es ausgeschlossen haben .,-Alle ohne Fehlercode .
Was StyloBot Ihrer TypeScript-Anwendung gibt, ist ein Urteil ein typisiertes Ergebnis mit einer kontinuierlichen Bot Wahrscheinlichkeitsbewertung.AiBot, Scraper, GoodBot, MaliciousBotWas Sie mit diesem Urteil tun, liegt bei Ihnen.
Dieser Artikel geht durch ein Beispiel storefront und zeigt, wie dieses Urteil wird Anwendungsverhalten an jeder Schicht .: ? Server-Middleware ?, ? Vorlage Helfer ? , ? und Browser-Komponenten ?
Das Urteil
Vor etwas anderem ist dies, was ankommt.
// @stylobot/core
interface Verdict {
isBot: boolean;
botProbability: number; // 0.0–1.0 - not binary, a continuous score
confidence: number; // certainty in that score
botType: BotType | null; // 'AiBot' | 'Scraper' | 'GoodBot' | 'MaliciousBot' | ...
botName: string | null; // 'GPTBot', 'Googlebot', 'curl/8.9.1', ...
riskBand: RiskBand; // 'VeryLow' | 'Low' | 'Elevated' | 'Medium' | 'High' | 'VeryHigh'
recommendedAction: RecommendedAction; // 'Allow' | 'Throttle' | 'Challenge' | 'Block'
threatScore: number; // elevated when CVE probes or credential stuffing detected
threatBand: ThreatBand; // 'None' | 'Low' | 'Elevated' | 'High' | 'Critical'
}
Ein Checkout-Endpunkt kann drosseln Medium Risiko statt zu blockieren Eine API kann ausschließen AiBot Verkehr von rate---Limit-Quoten, ohne es gegen reale Benutzer zu zählen, ein Anmeldeformular kann proof-MSC2-of---Arbeit für Elevated Risiko, ohne die Erfahrung für Low Risiko-Besucher-.-Nichts davon ist möglich, wenn das Erkennungsergebnis ein Boolean an der Netzwerkschicht ist..-
Risikobänder in der Reihenfolge VeryLow, Low, Elevated, Medium, High, VeryHigh, Verified.
Installation
npm install @stylobot/core @stylobot/node
# only needed for grpc mode
npm install @grpc/grpc-js @grpc/proto-loader
@stylobot/core hat Null Runtime Abhängigkeiten...... Es enthält die Typdefinitionen...... den REST Client... den Header Parser... und... den gRPC Client... es funktioniert in Node... und Bun ohne Modifikation....
@stylobot/node bietet Express-Middleware, ein Fastify-Plugin, einen Vorlagenhilfedienst und den Urteilsinjektor an. @stylobot/core und nichts anderes zur Laufzeit
Die Serveroberfläche
Wie das Urteil Ihre Middleware erreicht
Die Middleware hat drei Modi: Alle drei produzieren die gleichen req.stylobot Welche Sie verwenden, hängt davon ab, wo in Ihrer Infrastruktur-Erkennung läuft.
graph LR
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
subgraph H ["headers mode - zero added latency"]
GW[Gateway / Caddy / YARP]:::input -->|"X-StyloBot-* headers"| A[Express / Fastify]:::good
end
subgraph G ["grpc mode - HTTP/2, no JSON overhead"]
B[Express / Fastify]:::good -->|"gRPC Detect RPC"| SC[StyloBot Sidecar :5090]:::async
end
subgraph R ["api mode - REST, full signal set"]
C[Express / Fastify]:::good -->|"POST /api/v1/detect"| SC2[StyloBot Sidecar :5091]:::async
end
headers ModusDie Middleware liest injizierte Header ohne Netzwerkanruf. Das ist das Produktionsmuster, wenn ein Caddy- oder YARP-Gateway vorn sitzt.
grpc ModusDie Middleware ruft das Sidecar direkt über HTTP an. @grpc/grpc-jsDie gRPC-Schnittstelle und die Sidecar-Deployment Details sind in der Sidecar Architektur Artikel.
api ModusAnrufe POST /api/v1/detect auch über HTTP-/1.1.-Retouren reasons Beiträge von (, Per--, Detektor und signals Die volle Tafel Zustand, dass die anderen Modi weglassen
Die Middleware immer fehlschlägt offen, wenn das Sidecar unerreichbar ist oder mal aus,, req.stylobot wird zu einem freisprechenden leeren Urteil gesetzt und die Anfrage geht fort
Verkabelung
Ausdrucken
import express from 'express';
import { styloBotMiddleware } from '@stylobot/node';
const app = express();
app.use(styloBotMiddleware({ mode: 'headers' }));
// or:
app.use(styloBotMiddleware({ mode: 'grpc', endpoint: 'localhost:5090', timeout: 100 }));
Befestigen Sie die :
import Fastify from 'fastify';
import { styloBotPlugin } from '@stylobot/node';
const fastify = Fastify();
await fastify.register(styloBotPlugin, { mode: 'headers' });
Fügen Sie eine Typ-Deklaration hinzu, wenn Sie den eingegebenen Zugriff auf Fastify Requests wünschen.
// types.d.ts
import type { StyloBotResult } from '@stylobot/node';
declare module 'fastify' {
interface FastifyRequest { stylobot: StyloBotResult; }
}
Das Schaufenster
Die gleiche Probe storefront von der ASP-.-NET-ArtikelProduktseite , checkout-, login-Newsletter ,, aber in TypeScript. Das Detektionsergebnis ist das gleiche ;, was sich ändert, wie die Oberfläche es auslegt.
Seite Die Produktseite
Preiskratzer beginnen hier.Sie wollen Produktnamen, Preise und Lagerniveaus. Sie möchten den Katalog indexierbar durch Suchmaschinen und nützlich für Menschen, ohne die kommerziellen Signale an systematische Ernte zu übergeben.
Szenario: Ein Preiskratzer trifft /products/:idEs sieht keinen Rabattcode und kein Kaufsignal, das es wert ist auf zu handeln.
Der Routenbetreuer
app.get('/products/:id', (req, res) => {
const { verdict } = req.stylobot;
const product = getProduct(req.params.id);
res.render('product', {
product,
sbVerdict: verdict,
showDiscount: verdict.riskBand === 'VeryLow' || verdict.riskBand === 'Low',
showBuyButton: !verdict.isBot,
showCartWarning: verdict.recommendedAction === 'Challenge',
isSearchBot: verdict.botType === 'SearchEngine' || verdict.botType === 'VerifiedBot',
});
});
Die Schablone (Handgriffe ):
{{! verified crawlers get structured metadata instead of commercial UI }}
{{#if isSearchBot}}
<meta name="description" content="{{product.name}} -{{product.category}}." />
<p>{{product.description}}</p>
{{else}}
{{! discount only for low-risk human visitors }}
{{#if showDiscount}}
<div class="alert alert-success">
Member price: use code <strong>LOYAL10</strong> for 10% off.
</div>
{{/if}}
{{! add-to-cart only for non-bot traffic }}
{{#if showBuyButton}}
<form method="post" action="/cart/add">
<input type="hidden" name="productId" value="{{product.id}}" />
{{#if showCartWarning}}
<p class="text-warning">Additional verification may be required at checkout.</p>
{{/if}}
<button type="submit" class="btn btn-primary">Add to Cart</button>
</form>
{{else}}
<p class="text-muted">Purchase available to human visitors.</p>
{{/if}}
{{/if}}
Drei Muster im Gebrauch hier . . . . Crawler Differenzierung . SearchEngine und VerifiedBot erhalten Sie strukturierte Metadaten ohne kommerzielle Signale, die sie tatsächlich benötigen, um . . Discount-Targeting .: . ein Treuecode nur zu niedrig angezeigt ?- Risiko Verkehr ist weniger wahrscheinlich, auf einem Gutschein Forum enden . Challenge ist eine Warnung, die nicht ein Block sein kann.
Seite Auschecken
Betrugsautomatisierung,-Kartentester,-Gutscheinbrute--Streitkräfte,- und scripted Retries alle konvergieren bei Checkout.-Das Ziel ist die Verteidigung in der Tiefe ohne eine CAPTCHA---erste Erfahrung für jedermann.
Szenario: ein Gutschein für Bot-Hits /checkoutEs sieht eine tote message messaging messing send , die ein honigpot , - , ausgefülltes Formular , , , und erhält eine stille Bestätigung ohne erneuten Anreiz ,. ,
flowchart TD
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef problem fill:none,stroke:#ef4444,stroke-width:2px
A([Visitor reaches /checkout]):::input --> B{bot?}
B -->|yes| C[Dead-end message - no form]:::problem
B -->|no| D{risk band}
D -->|Low| E[Express checkout CTA]:::good
D -->|Elevated| F[Standard checkout CTA]:::good
D -->|High+| G[Phone number - no online path]:::problem
E & F --> H[POST /checkout/order]
H --> I{honeypot triggered?}
I -->|yes| J[Silent fake confirmation]:::problem
I -->|no| K[Process real order]:::good
Die Route
app.get('/checkout', (req, res) => {
const { verdict } = req.stylobot;
res.render('checkout', {
sbVerdict: verdict,
showForm: !verdict.isBot,
showExpress: verdict.riskBand === 'VeryLow' || verdict.riskBand === 'Low',
showStandard: ['VeryLow','Low','Elevated'].includes(verdict.riskBand),
showPhone: ['High','VeryHigh'].includes(verdict.riskBand),
});
});
app.post('/checkout/order', (req, res) => {
// honeypot fields are invisible to humans; bots fill everything
if (req.body.hp_name || req.body.hp_email) {
return res.redirect('/checkout/confirmed'); // silent fake - no retry incentive
}
return processRealOrder(req, res);
});
Die Vorlage
{{#if showForm}}
<form method="post" action="/checkout/order">
{{! invisible honeypot trap - humans leave blank, bots fill everything }}
<div style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
<input type="text" name="hp_name" tabindex="-1" autocomplete="off" />
<input type="email" name="hp_email" tabindex="-1" autocomplete="off" />
</div>
{{#if showExpress}}
<button type="submit" name="express" value="true" class="btn btn-success btn-lg">
Express Checkout
</button>
{{/if}}
{{#if showStandard}}
<button type="submit" class="btn btn-primary">Proceed to Payment</button>
{{/if}}
{{#if showPhone}}
<p>Please call us to complete your order: <strong>0800 123 456</strong></p>
{{/if}}
</form>
{{else}}
<p class="text-muted">Checkout is available to human visitors only.</p>
{{/if}}
Honeypot-Rückwurf ist hier die Schlüsseltechnik..-Fehler-Feedback lehrt Angreifer zu iterieren, ;-eine stille gefälschte Bestätigung verschwendet ihre Zeit und die Bestätigungsseite sieht identisch aus, ob der Auftrag real war oder verworfen wurde.MSC3-Express Checkout als Vertrauensvorteil. (-kein Default-)-Mittel nur Sitzungen, die es verdient haben, den kürzeren Pfad erhalten zu haben. <div> Wrapper in einen geteilten Lenker teilweise{{> honeypot}}Statt den Inline-Stilblock auf jeder geschützten Form zu wiederholen
Seite Anmeldung
Login is credential---Territorium - .-Der Handel ist anders als Checkout-:-ein falsches positives an der Kasse kann einen Verkauf verlieren , ;-ein verpasstes Credential---Füllen Angriff verliert ein Konto , .-Die Durchsetzung kann strenger sein ,.-
Szenario: Ein Credential-Skript trifft /loginEs sieht eine abschreckende Nachricht, die den Honigtopf füllt, und wird zu /login/denied bevor eine Authentifizierung ausgeführt wird.
app.get('/login', (req, res) => {
const { verdict } = req.stylobot;
res.render('login', {
sbVerdict: verdict,
showWarning: verdict.isBot,
showRisk: ['High','VeryHigh'].includes(verdict.riskBand),
});
});
app.post('/login', async (req, res) => {
if (req.body.hp_user || req.body.hp_pass) {
return res.redirect('/login/denied');
}
if (req.stylobot.verdict.isBot) {
return res.redirect('/login/denied');
}
return authenticate(req, res);
});
{{#if showRisk}}
<div class="alert alert-danger">
High-risk signals detected. Login attempts are logged.
</div>
{{/if}}
{{#if showWarning}}
<div class="alert alert-warning">
Automated login attempts are detected and blocked.
</div>
{{/if}}
<form method="post" action="/login">
<div style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
<input type="text" name="hp_user" tabindex="-1" autocomplete="off" />
<input type="password" name="hp_pass" tabindex="-1" autocomplete="off" />
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" autocomplete="email" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" name="password" autocomplete="current-password" />
</div>
<button type="submit" class="btn btn-primary">Sign In</button>
</form>
Der Bot sieht die Abschreckung vor dem Einreichen, wenn er ohnehin eingibt, der Honeypot fängt ihn, wenn es irgendwie das Honigtopf vermeidet. verdict.isBot ist die letzte Server-Prüfung, bevor jede Authentifizierungslogik ausgeführt wird, drei Schichten, alle kleinen
Seite Newsletter
KI-Crawler sind ein anderes Problem. Sie versuchen nicht, Brute--force Konten oder Erntepreise zu ernten.
Szenario: GPTBot-Treffer /newsletterEs sieht eine Datenlizenz-Nachricht statt eines Abonnements pech... Seine Einreichung wird stillschweigend verworfen.
app.get('/newsletter', (req, res) => {
const { verdict } = req.stylobot;
res.render('newsletter', {
sbVerdict: verdict,
isHuman: !verdict.isBot,
isAiBot: verdict.botType === 'AiBot',
isOtherBot: verdict.isBot && verdict.botType !== 'AiBot',
});
});
app.post('/newsletter/subscribe', (req, res) => {
if (req.body.hp_email2 || req.stylobot.verdict.isBot) {
return res.redirect('/newsletter/thanks'); // silent discard
}
mailingList.subscribe(req.body.email);
return res.redirect('/newsletter/thanks');
});
{{#if isHuman}}
<p>Get exclusive deals delivered to your inbox. Unsubscribe any time.</p>
{{/if}}
{{#if isAiBot}}
<div class="alert alert-info">
This subscription endpoint is for human readers.
For data licensing enquiries, <a href="/contact">contact us directly</a>.
</div>
{{/if}}
{{#if isOtherBot}}
<div class="alert alert-warning">
Automated subscription attempts are discarded.
</div>
{{/if}}
<form method="post" action="/newsletter/subscribe">
<div style="position:absolute;left:-9999px;opacity:0" aria-hidden="true">
<input type="email" name="hp_email2" tabindex="-1" autocomplete="off" />
</div>
<div class="form-group">
<input type="email" name="email" placeholder="[email protected]" autocomplete="email" />
</div>
<button type="submit" class="btn btn-success">Subscribe</button>
</form>
AiBot ist nicht nur ein anderes feindliches Label, es ist eine Klassifizierung, die eine geschäftliche Antwort ermöglicht... Eine Lizenz-Nachricht ist nützlicher als ein 403:. Es sagt einem Bediener, womit sie es zu tun haben und gibt ihnen eine Aktion zu ergreifen."..
Vorlagenhelfer
Injizieren des Urteils in Vorlagen
sbVerdictInjector läuft nach der Erkennung Middleware und setzt das Urteil auf res.locals:
import { sbVerdictInjector } from '@stylobot/node';
app.use(styloBotMiddleware({ mode: 'headers' }));
app.use(sbVerdictInjector({ mode: 'gateway' }));
// or for direct sidecar calls (REST port, not the gRPC port):
app.use(sbVerdictInjector({ mode: 'sidecar', endpoint: 'http://localhost:5091' }));
res.locals.sbVerdict ist in jeder Vorlage erhältlich. res.locals.sbVerdictScript ist ein Inline <script> Tag, das setzt window.__sb für die Browser-Komponenten
Lenker
Definieren RISK_ORDER einmal im Modulbereich verwenden die Helfer Nunjucks und EJS unten dieselbe Karte
import type { Verdict, RiskBand } from '@stylobot/core';
const RISK_ORDER: Record<string, number> = {
Unknown: 0, VeryLow: 1, Low: 2, Elevated: 3, Medium: 4, High: 5, VeryHigh: 6, Verified: 7,
};
// register on your Handlebars engine instance
hbs.engine({
helpers: {
// {{#sbGate sbVerdict "Low"}}...{{else}}...{{/sbGate}}
sbGate(verdict: Verdict | null, maxRisk: string, options: any) {
if (!verdict) return options.fn(this);
return RISK_ORDER[verdict.riskBand] <= RISK_ORDER[maxRisk]
? options.fn(this)
: options.inverse(this);
},
// {{#sbIsBot sbVerdict}}...{{else}}...{{/sbIsBot}}
sbIsBot(verdict: Verdict | null, options: any) {
return verdict?.isBot ? options.fn(this) : options.inverse(this);
},
// {{#sbBotType sbVerdict "AiBot"}}...{{/sbBotType}}
sbBotType(verdict: Verdict | null, type: string, options: any) {
return verdict?.botType === type ? options.fn(this) : options.inverse(this);
},
// {{#sbMinRisk sbVerdict "High"}}...{{/sbMinRisk}}
sbMinRisk(verdict: Verdict | null, minRisk: string, options: any) {
if (!verdict) return options.inverse(this);
return RISK_ORDER[verdict.riskBand] >= RISK_ORDER[minRisk]
? options.fn(this)
: options.inverse(this);
},
},
});
In Vorlagen
{{#sbGate sbVerdict "Low"}}
<a href="/checkout/express" class="btn btn-success">Express Checkout</a>
{{else}}
<a href="/checkout" class="btn btn-secondary">Checkout</a>
{{/sbGate}}
{{#sbBotType sbVerdict "AiBot"}}
<div class="alert alert-info">AI crawler detected. Data licensing info above.</div>
{{/sbBotType}}
{{#sbMinRisk sbVerdict "High"}}
<div class="alert alert-danger">High-risk session. Some features restricted.</div>
{{/sbMinRisk}}
Nunjucks
import nunjucks from 'nunjucks';
// RISK_ORDER - same map defined in the Handlebars section above
class SbGateExtension {
tags = ['sbgate'];
parse(parser: any, nodes: any, lexer: any) {
const tok = parser.nextToken();
const args = parser.parseSignature(null, true);
parser.advanceAfterBlockEnd(tok.value);
const body = parser.parseUntilBlocks('else', 'endsbgate');
let elseBody = null;
if (parser.skipSymbol('else')) {
parser.skip(lexer.TOKEN_BLOCK_END);
elseBody = parser.parseUntilBlocks('endsbgate');
}
parser.advanceAfterBlockEnd();
return new nodes.CallExtension(this, 'run', args, [body, elseBody]);
}
run(context: any, maxRisk: string, body: any, elseBody: any) {
const v = context.ctx.sbVerdict;
const fits = !v || RISK_ORDER[v.riskBand] <= RISK_ORDER[maxRisk];
return fits ? body() : (elseBody?.() ?? '');
}
}
env.addExtension('SbGateExtension', new SbGateExtension());
{% sbgate "Low" %}
<a href="/checkout/express">Express checkout</a>
{% else %}
<a href="/checkout">Checkout</a>
{% endsbgate %}
EJS
EJS hat nicht Block-Hilfskräfte, sondern lokale Funktionen decken die meisten Fälle sauber ab.
// RISK_ORDER - same map defined in the Handlebars section above
app.use((req, res, next) => {
const v = res.locals.sbVerdict ?? null;
res.locals.sbBelowRisk = (max: string) =>
!v || RISK_ORDER[v.riskBand] <= RISK_ORDER[max];
res.locals.sbAboveRisk = (min: string) =>
v && RISK_ORDER[v.riskBand] >= RISK_ORDER[min];
res.locals.sbIsBot = () => v?.isBot ?? false;
res.locals.sbBotIs = (type: string) => v?.botType === type;
next();
});
<% if (sbBelowRisk('Low')) { %>
<a href="/checkout/express" class="btn btn-success">Express Checkout</a>
<% } else { %>
<a href="/checkout" class="btn btn-secondary">Checkout</a>
<% } %>
<% if (sbBotIs('AiBot')) { %>
<div class="alert alert-info">AI crawler. Data licensing enquiries via /contact.</div>
<% } %>
Die Browseroberfläche
Injizieren des Urteils in den Browser
Hinzufügen {{{sbVerdictScript}}} zu deinem Layout-Kopf, es rendert als,:
<script>window.__sb = {"isBot":false,"botProbability":0.12,"riskBand":"Low","recommendedAction":"Allow",...}</script>
Dann laden Sie die Elemente Bundle-:
<head>
{{{sbVerdictScript}}}
<script type="module" src="/js/sb-elements.js"></script>
</head>
<sb-gate>Inhalt durch Risikoband anzeigen oder ausblenden
<!-- only shown when riskBand <= 'low' -->
<sb-gate max-risk="low">
<a href="/checkout/express" class="btn btn-success">Express Checkout</a>
</sb-gate>
<!-- only shown when riskBand >= 'elevated' -->
<sb-gate min-risk="elevated">
<div class="alert alert-warning">Unusual activity detected on your session.</div>
</sb-gate>
<sb-adapt>Wählen Sie den ersten passenden Fall
<sb-adapt>
<sb-case max-risk="low">
Standard checkout - enter your card details below.
</sb-case>
<sb-case max-risk="medium">
Additional verification is required before we can process your order.
</sb-case>
<sb-case>
Automated checkout access is not permitted.
</sb-case>
</sb-adapt>
<sb-adapt> wählt die erste <sb-case> deren max-risk passt und versteckt den Rest <sb-case> ohne max-risk ist der Catch---all-. <sb-gate> und <sb-adapt> Hören Sie auf die sb:verdict Ereignis und neu bewerten, wenn sich das Urteil nach der ersten Farbe ändert.
<sb-widget>:-Server , --rendered Flüssige Fragmente
<sb-gate> blendet Content Client aus--Seite. Wenn Sie einen Bot benötigen, um verschiedene Markups zu empfangen, müssen Sie das Fragment auf dem Server mit dem Erkennungskontext der Vorlage darstellen.
<sb-widget> liest eine flüssige Vorlage aus einer Inline <template> Element: , chargt alle Widget-Anfragen auf der Seite in eine einzelne Runde und ersetzt sich durch die zurückgegebene HTML-Version.
<sb-widget data-sb-widget="checkout-cta">
<template>
{% if recommendedAction == 'Block' %}
<p class="text-danger">Automated checkout is blocked.</p>
{% elsif botType == 'AiBot' %}
<p>AI crawlers cannot complete purchases. <a href="/contact">Data licensing enquiries</a>.</p>
{% elsif isBot %}
<p class="text-muted">Checkout is available to human visitors.</p>
{% else %}
<a href="/checkout/express" class="btn btn-success">Express Checkout</a>
{% endif %}
</template>
</sb-widget>
Vorlagenvariablen isBot, botProbability, confidence, botType, botName, riskBand, recommendedAction, threatScore, threatBandZusätzlich zu jeder vars wenn Sie vom Server übergeben werden. RenderWidget direkt - .-
Insgesamt <sb-widget> Elemente, die in der gleichen Microtask-Tick verbinden werden in eine Anfrage gechargt.Eine Seite mit fünf Widgets macht eine Runde.
sequenceDiagram
participant B as Browser
participant C as Coordinator
participant S as /_stylobot/partials/render
participant L as Fluid / Liquid
B->>C: sb-widget#checkout-cta registers
B->>C: sb-widget#promo-banner registers
B->>C: sb-widget#nav-links registers
Note over C: queueMicrotask - one batch
C->>S: POST { widgets: { checkout-cta: "...", promo-banner: "...", nav-links: "..." } }
S->>L: render each template with verdict context
L-->>S: rendered HTML fragments
S-->>C: <div data-sb-widget="checkout-cta">...</div> ...
C-->>B: each sb-widget replaced in DOM
Übersichtstabelle
Komponente |, Schicht |, was es tut
|---|---|---|
| styloBotMiddleware Anhängungen für Express-Anhänge req.stylobot über Kopfzeilen
| styloBotPlugin Verfeinern Sie das Plugin "Befestigen" mit decorateRequest |
| sbVerdictInjector Express-Bevölkerung res.locals.sbVerdict und sbVerdictScript |
Benutzer-Helfer für die Handgriffe Servervorlagen sbGate, sbIsBot, sbBotType, sbMinRisk Block-Hilfskräfte
Server-Vorlagen für die Erweiterung um Nunjucks {% sbgate "Low" %}...{% endsbgate %} |
EJS-Einheimische Servervorlagen sbBelowRisk(), sbAboveRisk(), sbIsBot(), sbBotIs() |
| <sb-gate> Browser Anzeige des / Ausblenden-Inhalts durch Risikoband lauscht für sb:verdict |
| <sb-adapt> Browser Wählen Sie den ersten passenden Fall aus einer Liste
| <sb-widget> Browser für |, Fetch-Server, -, gerendert Flüssiges Fragment, ,, gechargt pro Zecke, MSC4,
| StyloBotGrpcClient Direkter gRPC-Client für Nicht---Middleware-Anwendung
Der Nächste in der Release-Serie Die Sidecar-ArchitekturWie die Detektions-Engine mit Nicht--.-NET-Stacks verbunden wird, ist das Go SDK®,. Das Caddy-Plugin und die gRPC-Schnittstelle, die es miteinander verbinden.
Wenn Sie hier von der Seite des .-NET angekommen sind Verhalten Bewusst WERDEN deckt die gleichen storefront Muster mit Tag-Helper und Aktionsfiltern, die Zuverlässigkeit rework, die den Motor Speicher hält .- ist unter anhaltendem Verkehr in Ungebundenes Wachstum in langen --Diensten finden und behebenLive-Engine, Dashboard und kommerzielle Steuerungen am Stylobot-.-net.