agentleFS
AnyOrgNameAnyOrgName/php-skills/skills/bitrix/kernel-main-module/SKILL.md

kernel-main-module

Skill4 starsChanged 4 months agoMITView on GitHub

Work with the 1C-Bitrix `main` module kernel — bootstrap, the D7 Application / Context / Request services versus the legacy $APPLICATION / CMain globals, the event system, module inclusion, the service locator, and agents. Use when the user needs kernel bootstrap services in Bitrix — `Application::getInstance()`, the `Context`, the `Request`, the connection pool, or the service locator; the user wants to register or handle a Bitrix event — the D7 `EventManager`/`addEventHandler` or the legacy `RegisterModuleDependences`; the user needs to include a Bitrix module or connect code to the kernel — `Loader::includeModule()` (D7) or the legacy `CModule::IncludeModule()`; the user reads HTTP input in Bitrix and asks whether to use the D7 `Context::getRequest()` accessors or the legacy `$_REQUEST`/`$_GET` superglobals. Keywords: bitrix, kernel, main-module, d7, legacy, events, service-locator, input, security, битрикс, ядро.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 5 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not use this skill for pure content editing or template HTML/CSS work that does not touch kernel services, events, module inclusion, or …

    line 85
  2. Distinctive:

    Do not use this skill on a non-Bitrix PHP app (plain PHP, Laravel, Symfony).

    line 87
  3. Very specific:

    Verify: $em is a non-null EventManager instance.

    line 135
  4. Distinctive:

    Verify: The handler appears in the event map and fires on login.

    line 139
  5. Distinctive:

    Verify: The handler reads its payload from the Event object, not global state.

    line 142
  6. Very specific:

    Ensure the kernel is bootstrapped, then get the app with $app = \Bitrix\Main\Application::getInstance();.

    line 155
  7. Very specific:

    Verify: $app is a non-null Application instance.

    line 157
  8. Very specific:

    Verify: $request->getQuery('id') returns the query value without touching $_GET.

    line 160
  9. Distinctive:

    Verify: Invalid input is rejected before any query runs.

    line 163
  10. Very specific:

    Use Bitrix agents (CAgent::AddAgent) for periodic tasks that must run inside a bootstrapped kernel.

    line 167

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md
<!-- generated: do not edit — source: knowledge/atoms/bitrix/kernel-main-module/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->

Bitrix Kernel (main module)

When to use

  • The user needs kernel bootstrap services in Bitrix — Application::getInstance(), the Context, the Request, the connection pool, or the service locator.
  • The user wants to register or handle a Bitrix event — the D7 EventManager/addEventHandler or the legacy RegisterModuleDependences.
  • The user needs to include a Bitrix module or connect code to the kernel — Loader::includeModule() (D7) or the legacy CModule::IncludeModule().
  • The user reads HTTP input in Bitrix and asks whether to use the D7 Context::getRequest() accessors or the legacy $_REQUEST/$_GET superglobals.

When NOT to use

  • Do not use this skill for pure content editing or template HTML/CSS work that does not touch kernel services, events, module inclusion, or request handling.
  • Do not use this skill on a non-Bitrix PHP app (plain PHP, Laravel, Symfony); the main module and its globals do not exist outside 1C-Bitrix.

Core guidance

  • Prefer D7 kernel API for new code — In new code, reach for the D7 API first — \Bitrix\Main\Application, Context, HttpRequest, Loader::includeModule() — instead of $APPLICATION, CMain, or CModule::IncludeModule().
  • Read input through the kernel Request, not superglobals — Read HTTP input via Application::getInstance()->getContext()->getRequest() and its typed accessors (->getQuery(), ->getPost()) rather than touching $_GET/$_POST directly.

Decision Engine

Walk this section before choosing an implementation path.

Are you writing new kernel code, or editing an existing legacy code path?

├── Editing legacy path: → legacy — keep the existing legacy API and make a minimal local edit; do not rewrite to D7 opportunistically.

└── New code: Does the API you need exist in the D7 namespace (\Bitrix\Main\...)?

    ├── D7 exists: → d7 — use Application/Context/Request, Loader::includeModule, and EventManager.

    └── No D7 equivalent: → legacy — call the legacy API (e.g. CMain method) behind a thin adapter so call sites stay D7-shaped.

Full engine: references/decision-engine.md — Decision Tree, Priority Matrix, Decision Table.

Workflows

Workflow: Register Event D7

Progress:
- [ ] Get the manager with
`$em = \Bitrix\Main\EventManager::getInstance();` inside the module `init.php`
- [ ] Register with
`$em->addEventHandler('main', 'OnAfterUserLogin', [MyHandler::class, 'onLogin']);`
pointing at a static method
- [ ] In the handler, accept a `\Bitrix\Main\Event $event` and read parameters with
`$event->getParameter('USER');` instead of relying on positional arguments
  1. Get the manager with $em = \Bitrix\Main\EventManager::getInstance(); inside the module init.php.
    • Verify: $em is a non-null EventManager instance.
  2. Register with $em->addEventHandler('main', 'OnAfterUserLogin', [MyHandler::class, 'onLogin']); pointing at a static method.
    • Verify: The handler appears in the event map and fires on login.
  3. In the handler, accept a \Bitrix\Main\Event $event and read parameters with $event->getParameter('USER'); instead of relying on positional arguments.
    • Verify: The handler reads its payload from the Event object, not global state.

Workflow: Read Request D7

Progress:
- [ ] Ensure the kernel is bootstrapped, then get the app with
`$app = \Bitrix\Main\Application::getInstance();`
- [ ] Get the request via `$request = $app->getContext()->getRequest();` and read a
value with `$request->getQuery('id')`, treating it as untrusted
- [ ] Validate the raw value at the boundary (e.g
  1. Ensure the kernel is bootstrapped, then get the app with $app = \Bitrix\Main\Application::getInstance();.
    • Verify: $app is a non-null Application instance.
  2. Get the request via $request = $app->getContext()->getRequest(); and read a value with $request->getQuery('id'), treating it as untrusted.
    • Verify: $request->getQuery('id') returns the query value without touching $_GET.
  3. Validate the raw value at the boundary (e.g. cast to int and reject non-positive ids) before passing it into domain or ORM calls.
    • Verify: Invalid input is rejected before any query runs.

Best practices

  • Use Bitrix agents (CAgent::AddAgent) for periodic tasks that must run inside a bootstrapped kernel; move heavy or precisely-timed jobs to OS cron running an agent script with define('BX_CRONTAB', true)
  • Register new handlers with EventManager::getInstance()->addEventHandler() (or the module .php event map) and keep legacy RegisterModuleDependences only for old events that have no D7 counterpart
  • Guard every Loader::includeModule('iblock') (or legacy CModule::IncludeModule) with a check on its boolean return and bail early when the module is missing
  • Resolve shared services with ServiceLocator::getInstance()->get('code') and register them in .settings.php instead of instantiating singletons by hand

Anti-patterns

Anti-patternWhy it failsDo instead
New code leaning on $APPLICATION globalsGlobal state is implicit, untestable, and couples new code to legacy bootstrap order.Resolve services through Application::getInstance() and the Context; keep the<br>legacy globals only inside legacy files you are not refactoring.
Opportunistic D7 rewrite during an unrelated fixThe rewrite widens the diff and risks changing behavior the task never intended to touch.Keep the scoped fix minimal; propose the D7 migration as a separate, signed-off task.
Ignoring the module inclusion resultWhen the module is absent the call returns false and the next class reference fatals.Branch on the boolean result and stop with a clear message if the module is missing.

See references/anti-patterns.md.

Debugging

  1. Time-critical agent drifts under low traffic — Agents without cron are scheduled by page hits, not by wall-clock time. Fix: Run agents from OS cron with define('BX_CRONTAB', true) for time-critical jobs so execution no longer depends on incoming traffic.
  2. Accessing Application before the kernel is bootstrapped — The Application singleton and Context are only populated after the prolog bootstraps them. Fix: Bootstrap the kernel (prolog for web, or the documented CLI bootstrap with define('NO_KEEP_STATISTIC', true) and the agent/cron entry) before touching services.
  3. Trusting raw superglobals in kernel code — Scattered superglobal access hides the input boundary and invites injection and test gaps. Fix: Read through Context::getRequest() accessors and validate the value at the boundary before it reaches domain logic.
  4. Using module classes before including the module — Autoloading for a module is only wired up after the module is included. Fix: Include the module first and check the boolean result; only then reference its classes, returning a handled error if inclusion fails.

Production checklist

  • New event handlers are registered through the EventManager or the module event map, not scattered inline in templates or init.php with duplicate registrations.
  • Edits to legacy code paths are minimal and reversible, with no opportunistic rewrite of a working legacy API into D7 during an unrelated change.
  • Every Loader::includeModule() result is checked and the code bails out cleanly when a required module is not installed.
  • New code does not add fresh dependencies on $APPLICATION, $USER, or $DB globals; it resolves the D7 equivalents (Application, CurrentUser, connection).
  • HTTP input is read through the kernel Request accessors and validated at the boundary rather than pulled directly from $_GET/$_POST.

Version notes

  • D7 core API arrived with the D7 platform — The namespaced D7 kernel (\Bitrix\Main\Application, Context, Loader, EventManager) became the recommended core API from the D7 platform (main ~14+); older projects mix it with the legacy C* classes.
  • PHP support tracks the Bitrix core version — Modern Bitrix cores run on PHP 7.4 through 8.2; the kernel and stock modules were not certified past 8.2 at the time of writing, so avoid relying on PHP 8.3+ syntax in kernel-adjacent code.

Security

  • Validate kernel request input at the boundary — Treat every value from the kernel Request (getQuery, getPost, getCookie) as untrusted: validate and cast it at the controller boundary, and never pass a raw request value straight into SQL, filesystem, or eval-like calls.

Testing

  • Activation and decision behavior are verified in eval/scenarios/bitrix/kernel-main-module.yaml.

Additional resources

  • references/anti-patterns.md
  • references/core.md
  • references/decision-engine.md
  • references/examples.md
  • references/pitfalls.md
  • references/recipes.md
  • references/version-differences.md

Knowledge graph

Related: audit/bitrix, bitrix/cache-layers, php/class-constants
Behavior constraints: ai-rules/strategy-legacy-safe-edits

<!-- graph-fragment: graph/fragments/bitrix/kernel-main-module.yaml -->

Skill contract

Produces: bitrix.kernel-bootstrapped
Requires: stack.bitrix
Risk: medium · Confidence: 0.9

<!-- contract-fragment: contracts/fragments/bitrix/kernel-main-module.yaml -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.