Виокремлення Bot не має зупинятися на дозволяти/блокуM SK1 Цей пост показує, як результат класифікації StyloBot ' стає логікою застосування в шрифті TypeScript МSK3 серверному середовищі для Express і Fastify МСК4 шаблонних вказівників для ручних панелей М СК5 Nunjucks М סК6 та EJS М S К7 і веб-компонентах браузера М ็ С К8 так що ваше інтерфейс може формувати досвід замість того, щоб відштовхувати тремтіння після факту M С К9
І
@stylobot/coreі@stylobot/nodeпакети npm незабаром будуть опубліковані. Ниже представлені фрагменти описують поверхню, яку вони відкриють.
Серія випуску StyloBot
- Подібність, Не ідентичність: чому StyloBot моделює клієнтів поведінково
- Подібність-Усвідомлення ASP.NET UI: сервер - віддалена поверхня для МSK2NET застосувань
- Винайти та виправити безмежний ріст у довгостроковій-Running M SK1NET Services: - дисципліна надійності, яка робить двигун нудним в процесі виробництва
- Подібність-Усвідомлення інтерфейсу TypScript: цей artykuł
- Архітектура Sidecar: як реагуючий двигун підключається до не МSK1NET стеків
- Навчитися швидше: адаптивна система навчання , чотири МSK2 пам 'ять на рівні M SK3 і кэш вердикта
- Випробовуємо те, що не зупиняє нас: контрольна дисципліна : один БДФ файл керує регресією МSK2 завантаженням МСК3 та калібрацією
- StyloExtract - локальний інтерфейс навчання HTML для конвертера Markdown: HTML → Марка-даун, який поєднується з детектором МSK2 walker bug lucidVIEW caught МSK3 and the dogfood loop that made it honest
Мотор розпізнавання StyloBot , написаний в ASP, ., NET Core і :, має високий "-" показник, з чудовими асинковими примітивами. МSK4, суб--, мулісекундний гарячий , МSK6, затримка маршруту, МSK7, а за ним - двадцять років виробництва. .. СDK TypScript - це поверхня, яка переносить вихідного коду МSK9 до Node, Applications and Browsers without requiring either to know anything about what happened underneath (не обов 'язково знати нічого про те, що сталося під ним). Навчитися швидше: після того, як відбитки пальців побачили з достатньою впевненістю
Більшість розпізнавання роботів, доступних в екосистемі TypScript, дає вам одне з двох речей - : - відбитки пальців браузера, які показують, чи клієнт виглядає автоматизовано, або регекс через Пользователя
Ни одна з них не є корисною на рівні застосування.
бод запускається в браузері і не має доступу до заголовків запитів, відбитки пальців TLS , поведінка сеансу МSK2 чи IP репутація M SK3 Безголовний хром і Googlebot виглядають однаково з ним . Пакети, які відповідають чистому стандарту UA | (is-bot, isbot) ловити тільки те, що дозволяє бути пойманим . Мережа МSK2 продукти на шарі МSK3 Zarządzanie дротом Cloudflare M SK4 DataDome ) блокувати на краю, але не вміти персоналізувати на рівні додатку MSC6 Ви дізнаєтесь, що прохання було заблоковано М SK7 ніколи не було так, щоб прохання, яке прийшло до вашої додатки, мало шансу бути МСК8 ботом і середній ризиковий діапазон М СК9 таким чином ваша сторінка скриньки могла б показати крок тремтіння, а ваші аналітики могли б його виключити M СК10 все без коду помилок М S К11
Те, що StyloBot дає вашій програмі TypScript - це вердикт: задрукований результат з послідовним балом ймовірності роботаM SK1 класифікація (AiBot, Scraper, GoodBot, MaliciousBotМСК0 ...), групи ризику , запропонована дія МSK3 і бал загрози мSK4 Те, що ви робите з цим вердиктом, залежить від вас
У цій статті ми проглянемо зразок магазину і покажемо, як це рішення перетворюється на поведінку aplikacji на кожному шарі.
Перш ніж будь-що інше, це те, що приходить.
// @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'
}
Вказівний пункт може рухатись Medium ризик, замість блокування його. API може виключити AiBot рух з тарифу-limit квоти без підрахунку його проти реальних користувачівM SK1 Заявка для входу може додати доказиMSC2of-праця для Elevated ризик, не торкаючись досвіду Low відвідувачі з ризиком. Нічого з цього неможливих, якщо результат виявлення є boolним на рівні мережі
Ризикові групи у порядку: VeryLow, Low, Elevated, Medium, High, VeryHigh, Verified.
npm install @stylobot/core @stylobot/node
# only needed for grpc mode
npm install @grpc/grpc-js @grpc/proto-loader
@stylobot/core має нульowe залежності від часу запуску. Він містить визначення типів , klient REST МSK2 розшифровувач заголовків M SK3 і ( опціонально MSC5 gRPC М SK6 Він працює в Node МSK7 Deno \ , та Bun без модифікації M SK9
@stylobot/node надає програмне забезпечення Express middleware, плагин Fastify , шаблони допоміжні інструментиM SK2 і ін 'єктор вердикта. Це залежить від @stylobot/core і нічого іншого в часі запуску.
Посередник має три режими. Усі три виробляють те ж саме req.stylobot форма. Який ви використовуєте залежить від того, де працює детектор вашої інфраструктури
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 режим: розпізнавання відбувалося вгорі на шлюзі ; посередник читає в 'єковані заголовки без зв' язку з мережею МSK2 Це модель виробництва, коли фронтальна шлюза Caddy чи YARP
grpc режим: посередник набирає автозаряду прямо через HTTP /2. Найнижча затримка МSK2 не потребує JSON над głową @grpc/grpc-js. Шлях інтерфейсу gRPC і деталі розгортання бокового авто знаходяться в Статья про архітектурну галерею.
api режимЗапроси : POST /api/v1/detect над HTTP/1.1. Далі повертається reasons (в залежності від-врахунки детекторівМSK2 та signals (повне состояние чорної дошкиM SK1, яке інші режими забувають
Посереднє програмне забезпечення завжди не працює. req.stylobot встановлений до припустимого пустого вердикту, і запити продовжується.
Express:
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 }));
Зарядити:
import Fastify from 'fastify';
import { styloBotPlugin } from '@stylobot/node';
const fastify = Fastify();
await fastify.register(styloBotPlugin, { mode: 'headers' });
Додайте декларацію типу, якщо ви хочете мати встромлений доступ до застегнених запитів:
// types.d.ts
import type { StyloBotResult } from '@stylobot/node';
declare module 'fastify' {
interface FastifyRequest { stylobot: StyloBotResult; }
}
Те ж саме зразок магазину з Artykuł ASP.NET, сторінка товаруM SK1 вирахунок, login , бюллетень МSK4 але в шрифті TypeScript M SK5 Результат виявлення один і той самий MSC6 що змінюється - це те, як поверхня виявляє його .
Цінники починають ось тут. Вони хочуть назвати товариM SK1 ціни, і рівня запасівMSC3 Ви хочете каталог, який можна indeksувати пошуковими машинами та бути корисним для людей, не передаваючи коммерческих сигналів систематичному вилову .
Scenario: знижує ціни /products/:id. Він не бачить коду зniżki , не додасть M SK2 до - кнопки картки МSK4 і ніякого сигналу купівлі, який варто використовувати на .
Керівник маршруту:
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',
});
});
Шаблона (Handlebars):
{{! 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}}
Три візерунки, які тут використовуються. Диференціація КраулераM SK1 SearchEngine і VerifiedBot отримати структуровані метадані без комерційних сигналів Challenge є попередженням , не блоком. Небезпечні сеанси все ще можуть купити МSK2
Автоматизація шахрайства, тестувальники картM SK1 брутовий ваучер- форсирівці , і сценарійні ретриси всі сходяться під час зарахункуMSC4 Метою є оборона в глибині без CAPTCHAМSK5перший досвід для всіхMСК6
Scenario: ваучерM SK1 спроби bot hits /checkout. Він бачить мертвуM SK1 закінчується повідомлення , надсилає медовий чайник M SK3 заповнений бланк , і отримує мовчазне підтвердження без стимулу для повторного спробування MSC5
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
Дорога:
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);
});
Шаблона:
{{#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}}
Тут ключовою технікою є відкидування медоносів.. Відповідь про помилки вчить атакующих повторювати. ; мовчазна фальшива підтвердження марнує їхній час. МSK2 і сторінка підтвердження виглядає однаково, чи замовлення було справжнім, чи відкидано.МSK3 Express Checkout як перевага довіри. <div> конвертер у спільний панель руль ({{> honeypot}}) замість того, щоб повторити блок встромного стилю на кожній захищеній формі
Вход є важливим- підтримка територіїM SK1 ТоргівляМSK2 викидка відрізняється від купівлі-продажі МSK3 хибний позитивний результат при купівці може втратити продажи ; пропущена важлива особистість М SK5 атака підтримуки втрачає свій рахунок M SK6 правопорядок може бути жорстокішим
Scenario: credentialM SK1 закінчується сценарійом /login. Він бачить попереджувальне повідомлення , заповнює горшок з медом МSK2 і повертається до /login/denied перед тим, як аутентифікувати.
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>
Робот бачить попередження перед тим, як відправити. Якщо він так чи інакше відправитьM SK1 медовий сад його спіймає . Якщо якимось чином він уникає медового саду, verdict.isBot є кінцевим сервером- перевірка боків перед запуском будь-якої логіки аутентифікації
Шриверки штучного інтелекту є іншою проблемою. МСК0 Вони не намагаються brute МСК1 наполягати на рахунках чи ціних на здобуток. МSK2 вони вживають контент для тренування моделей . Часто вони чесні щодо ідентичності , що означає, що правильна реакція - коммерційна, а не протистояння
Scenario: GPTBot hits /newsletter. Він бачить повідомлення про ліцензію даних замість подписки
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 це не просто інший ворожий ярлик, це класифікація, яка дозволяє бізнесу реагувати на нього.
sbVerdictInjector запускає посереднє програмне забезпечення для виявлення і додає вирок 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 є доступним в кожному шаблоні. res.locals.sbVerdictScript є встромним <script> ярлик, що визначає window.__sb для компонентів браузера.
Визначати RISK_ORDER як тільки на рівні модуля (нижні вправники Nunjucks та EJS користуються однією картою ):
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);
},
},
});
У шаблонах:
{{#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}}
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 не має блокастерів,, але локальні функції захищають більшість випадків
// 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>
<% } %>
Додайте {{{sbVerdictScript}}} до вашої головки макету. Він відображається якM SK1
<script>window.__sb = {"isBot":false,"botProbability":0.12,"riskBand":"Low","recommendedAction":"Allow",...}</script>
Далі завантажити пакет елементів:
<head>
{{{sbVerdictScript}}}
<script type="module" src="/js/sb-elements.js"></script>
</head>
<sb-gate>: показувати або приховувати контент, в залежності від групи ризику<!-- 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>: вибрати перший збіговий випадок<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> вибирає першу <sb-case> чиї max-risk вміщає та приховує решту. Остання <sb-case> без max-risk вловлення. <sb-gate> і <sb-adapt> слухати sb:verdict і ре-оцінити, чи змінюється вирок після першого малюнкуM SK1
<sb-widget>: сервер<sb-gate> закриває клієнта контенту-замістьМSK1 Якщо вам потрібен робот, щоб отримати інший маркупM SK2 не прихований маркуp, вам потрібно відтворити фрагмент на сервері з контекстом розпізнавання, доступним для шаблону .
<sb-widget> читає шаблон Рідкий з лінії вказівок <template> елемент, перетворює всі запити на widget на сторінку в один об 'єктM SK1trip, і заміняє себе поверненим HTML :
<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>
Променні шаблону: isBot, botProbability, confidence, botType, botName, riskBand, recommendedAction, threatScore, threatBand. плюс будь-яка vars ви переходите з сервера-замість при телефонуванні RenderWidget безпосередньо.
Все <sb-widget> елементи, які під 'єднуються в одному мікрозадачному значку, поєднані в один запит. сторінка з п' ятьма виджетами робить одну круглу
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
| Komponenт МSK1 Слой МSK2 Що він робить | ||
|---|---|---|
styloBotMiddleware |
Экспресс МSK1 Прикріплення req.stylobot через заголовки / gRPC / REST МSK2 |
|
styloBotPlugin |
Фастифікувати | Те ж саме МSK2 як плагин для фастифікування з decorateRequest |
sbVerdictInjector |
Экспресс МSK1 Населення res.locals.sbVerdict і sbVerdictScript |
|
| Допоміжні вказівники на панелі дотиків | Шаблони сервера МSK2 sbGate, sbIsBot, sbBotType, sbMinRisk допоміжні блоки |
|
| Поширення Nunjucks | Шаблони для серверів МSK2 {% sbgate "Low" %}...{% endsbgate %} |
|
| локальні EJS | Шаблони серверів МSK2 sbBelowRisk(), sbAboveRisk(), sbIsBot(), sbBotIs() |
|
<sb-gate> |
Переводник | Помічати МSK2 приховувати контент за групи ризику sb:verdict |
<sb-adapt> |
Веб-браузер | Виберіть перший збіговий випадок з списку МSK2 |
<sb-widget> |
Веб-браузер | |
StyloBotGrpcClient |
Мережа МSK1 Бан МSK2 Дено | Прямий gRPC-клиент для не мSK4з середнім програмним забезпеченням M |
Далі в релізовій серії: Архітектура Sidecar, як детектор з 'єднується з не--. NET-стаками , Go SDK МSK3 плагином Caddy M SK4 і інтерфейсом gRPC, який об' єднує його з собою .
Якщо ви прибули сюди з боку .NET , Подібність-Усвідомлення ASP.NET UI об 'єднує ті ж самі моделі фронту магазину з допомогою помічників та фільтрів дій; реновація надійності, яка зберігає пам' ять двигунаM SK1 стабільність під постійним рухом Винайти та виправити безмежний ріст у довгостроковій-Running M SK1NET Services. Живий двигун , панель управления МSK2 та коммерціальні прилади stylobot.net.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.