Базовое веб-приложение сервиса, служащее основой для всех остальных модулей и объединяющее их в единое решение. Состоит из отдельных Django-приложений, которые подключаются как модули, обеспечивая расширяемость и повторное использование кода.

ShariX Developer 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
bin 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
core 18fd81dc43 Harden LDAP registration consistency 5 days ago
docs 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
migrations a4fe48e299 fix migrations for the future 3 months ago
sharix_admin 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
.env.example afa32ada7a S92.1 2 weeks ago
.env_correct 8e680545af coding policy and theme editor 2 months ago
.gitattributes b32fae4d7a Added a new project configuration method 3 years ago
.gitignore d9d6384eda Stabilization S.6 Open UI regressions 4 weeks ago
AGENTS.md 5eca56c43a S92.10 cover module-owned Blockly provenance 2 weeks ago
CODING_POLICY.md 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
COMPLIANCE.json c70776ffa0 Stage 16.5 compliance and proprietary capability resilience 1 month ago
COMPLIANCE.md c70776ffa0 Stage 16.5 compliance and proprietary capability resilience 1 month ago
LICENSE fe8269a57b stage 16.1 1 month ago
README.md 5f81656360 Clarify API-key setup and client UI with shared copy control 10 hours ago
RELEASE_POLICY.md 5eca56c43a S92.10 cover module-owned Blockly provenance 2 weeks ago
admin.py 00c3a6c25b Some changes from students 4 months ago
constraints.txt f54cd9fec3 S92.7: replace CKEditor 4 with editor-neutral rich text 2 weeks ago
license-eng.md 95efa4ffb8 Added licenses 3 years ago
license-ru.md 95efa4ffb8 Added licenses 3 years ago
manage.py 98420a2f9c first commit 3 years ago
models.py f54cd9fec3 S92.7: replace CKEditor 4 with editor-neutral rich text 2 weeks ago
requirements.txt f54cd9fec3 S92.7: replace CKEditor 4 with editor-neutral rich text 2 weeks ago
sharix_config_io.py d9d6384eda Stabilization S.6 Open UI regressions 4 weeks ago

README.md

ShariX Open Webapp Base

The base Django project of a service web application to which other modules are connected.

Installation / Upgrade

The installation-local configuration lives in conf-real; working .env and bin/install.cfg are symlinks managed by bin/configure_local_configs.sh.

Typical first installation:

./bin/install.sh

On the first run the installer creates the local install.cfg from bin/install.cfg.example and stops so installation-specific repository URLs and the operational branch/optional repository overrides can be reviewed. The next run creates .env from .env.example and stops so database/integration settings can be filled. Run ./bin/install.sh again after configuration.

On upgrades the installer automatically appends missing keys only from bin/install.cfg.example into the local install.cfg. Existing local repository URLs and explicit branch overrides are preserved. Legacy all-master configs are normalized to one OPERATIONAL_BRANCH plus only non-default overrides.

Stage 19 branch control uses one normal selector:

OPERATIONAL_BRANCH="master"

A repository-specific *_BRANCH is written only for a real exception. Use ./bin/switch-all-branches.sh <branch> for a mass operational switch, --repo <path> <branch> for one override, and --repo <path> --use-operational to remove an override.

Optional modules are read from INSTALLED_APPS_LOCAL. Public modules may be selected from the ShariX Sysadmin catalogue; private modules are installed by an explicit repository URL. Both use the same install.cfg and installer path.

Installation languages are configured in .env with UI_LANGUAGES, CONTENT_LANGUAGES, and CONTENT_PRIMARY_LANGUAGE. UI_LANGUAGES is limited to installed static catalogs; content languages are independent and do not require the optional translations module. After updating .env.example, use the existing conf/utils/normalize_env.py diff/write/check lifecycle so local values are preserved.

The installer never creates migration files. Before applying migrations it runs:

./venv/bin/python manage.py makemigrations --check --dry-run

If model state differs from committed canonical migrations, installation stops. Create/fix the migration in the repository that owns the model, commit it, and then rerun installation.

Assembly audit

Run the read-only audit before and after a substantial update:

./bin/audit_installation.sh

It checks repository wiring, local-module configuration, .gitignore coverage, Django system checks, model/migration consistency, migration plan readability and installed design themes. It does not pull repositories, change configuration, migrate the database or run collectstatic.

Stage 15 adds a DB-independent cross-assembly closeout entry point:

./bin/check_acceptance.sh

The default run uses zero-network guards and only Django SimpleTestCase/pure checks, so it does not create a separate test_* database. Use --with-runtime-audit after that pass when the configured installation database and normal assembly audit are available.

Public source/module transparency

Stage 16.4 exposes the running Service source/module projection at:

/source/
/.well-known/sharix-source.json

The projection is generated from the current installation configuration and materialized checkouts. GPL/AGPL components show public repository/ref evidence; private modules show only non-sensitive module/license state. Repository credentials, private repository URLs, API keys, local filesystem paths and offline-entitlement secrets are never part of the public projection.

For AGPL components canonical upstream is the normal case, but it is not used as a fallback when the running tree differs. Inspect current evidence with:

./venv/bin/python manage.py source_publication status

For a rare divergent deployment, publish the matching source first and verify it before recording the public evidence:

./venv/bin/python manage.py source_publication set-override \
  BACKEND https://example.org/organization/public-fork.git main

To change the deployment source itself, switch-source first verifies the destination anonymously against the running source and only then updates the existing bin/install.cfg repository/branch contract. Continue with the normal bin/repositories.sh workflow printed by the command; do not maintain a second source-mode setting.

Normal operator shell entrypoints under bin/ source bin/utils/no_pager.sh, which sets PAGER, GIT_PAGER, SYSTEMD_PAGER, PSQL_PAGER and MANPAGER to cat. Routine scripts therefore print directly to the terminal rather than opening an interactive pager. The contract is checked by bin/checks/no_pager_contract.py.

Installation app systemd service

run script

./bin/install_service.sh

systemctl basic

show status:

systemctl status opensharix.service

restart:

systemctl restart opensharix.service

stop:

systemctl stop opensharix.service

start:

systemctl start opensharix.service

Reference demo users

Stage 8 reference users are described canonically in conf/demo/open-reference/personas.json and generated into LDAP from the same source. Their historical short UIDs (2101, 2201 ... 6103) are retained only for the reference environment.

With METASERVICE_ID=0, TEST users are available even when DEBUG=False. After switching Open to a positive metaservice ID they are blocked unless DEBUG=True is intentionally enabled for diagnostics; data scoping still stays on the current metaservice ID.

After synchronizing LDAP, a reference installation uses:

METASERVICE_ID=0
PAYMENT_PROCESSING_MODE=platform
PAYMENTS_SUBSCRIPTIONS_ENABLED=true

and materializes/audits the Stage 8 business layer with:

./venv/bin/python manage.py ensure_demo_scenario
./venv/bin/python manage.py ensure_demo_scenario --check

Stage 8 adds three simultaneous catalogue scenarios (ordinary paid, subscription and free), nine user-visible tariffs, three active offers for every reference Provider persona, and installed-module examples for Payments, Service Constructor, Appointments, Moodle and Legal. Namespace 0 keeps Platform as the configured payment owner but uses a local explicit no-money backend, so it never calls Platform or a bank and never fabricates finance transactions.

Stage 8.4 integrates the reference environment into bin/install.sh: a canonical new installation with METASERVICE_ID=0 synchronizes reference LDAP identities, runs ensure_demo_scenario, and immediately runs the read-only --check. A positive-ID installation skips demo business bootstrap. The production command performs a collision preflight and refuses to overwrite unrelated data occupying a reserved reference UID/INN/codename.

For the full persona matrix, catalogue, recovery workflow and existing-install LDAP synchronization commands, see docs/test-users.md and conf/demo/open-reference/README.md.

Configuration

For basic project configuration when deploying, use the core/settings_vars.py. This file is automatically created during the installation script execution, in case this file has not been created yet. It is a copy of core/ _settings_vars.py and contains some default settings that allow the project to run locally and is more suitable for development.

Be careful when adding new settings during development and remember to add them to core/_settings_vars.py, as core/settings_vars.py is ignored by Git for security reasons.

You can also change the settings in bin/install.cfg. This file contains the links to repositories required for the project to work.

Shared-module configuration parity (Stage 18.1)

Open и Platform используют разные корневые .env.example, но параметры реально общих модулей проверяются по conf/shared-env-contract.json. Обычный bin/check_acceptance.sh запускает DB-independent local parity guard. После pull обновлённого example существующий conf-real/.env нормализуется безопасным циклом:

./venv/bin/python conf/utils/normalize_env.py --only-root --diff
./venv/bin/python conf/utils/normalize_env.py --only-root --write
./venv/bin/python conf/utils/normalize_env.py --only-root --check

Значения секретов в --diff редактируются; после изменения startup settings перезапустите соответствующий service.

Platform integration profiles (Stage 13.1)

Open now supports two explicit Service -> Platform connection profiles in the root .env: Production and Testing. The Production API URL defaults to https://sharix-app.org/my/api/; the Testing URL remains deployment-owned. PLATFORM_INTEGRATION keeps its existing lifecycle/status meaning and is not the server selector.

A pre-Stage-13 installation that has only PLATFORM_API_URL / PLATFORM_API_KEY remains in legacy-unclassified compatibility state: the exact old pair stays effective and no hostname heuristic is used. Classify it explicitly before switching profiles:

./venv/bin/python manage.py adopt_platform_integration_profile production
# or
./venv/bin/python manage.py adopt_platform_integration_profile testing

The selected profile owns the canonical URL/key. Since Stage 15.4, the established PLATFORM_API_URL / PLATFORM_API_KEY names are runtime-only in-memory compatibility aliases derived from that selected canonical profile. They are not active installation settings after explicit adoption; historical assignments are moved to MAYBE OBSOLETE by conf/utils/normalize_env.py. See docs/stage13_platform_integration_source_audit.md for the historical 13.1 audit and docs/platform-integration-modes.md for the current contract.

Stage 13.2 centralizes all governed outbound Platform target selection in dbsynce.lib.platform_integration.runtime and sends governed HTTP operations through dbsynce.lib.platform_integration.transport. In-tree callers must not independently choose Production/Testing credentials or call Platform with a direct requests.* transport. bin/checks/platform_outbound_boundary.py enforces this boundary.

Stage 13.3 defines local Demo precisely as METASERVICE_ID=0 plus PLATFORM_INTEGRATION_SERVER=testing: it performs no Platform HTTP and does not read a Platform API key. A positive ID with Testing is different — it performs real HTTP against Testing Platform and is the supported API-debugging path. DEBUG remains independent from both. Stage 13.4 adds superuser-only switching between existing metaservice profiles with a pending-on-disk state and session generation guard; changes become active after coordinated restart.

For a failed Service activation request, Open performs a Service-side diagnostic recheck without changing the Platform API contract: it compares the control status, linked integration ticket and locally confirmed integration status before and after the request. Non-JSON Platform errors are reduced to a short safe summary (for example an HTTP error-page title); full debug HTML and API keys are never shown. A historical background-sync error is displayed separately from the current activation-attempt diagnostic.

Release 0.9.2 R92.4 makes recovery explicit. The Service UI treats the current Platform status and the canonical activation ST_REQUEST as remote truth, while the .env target and the last locally stored confirmation remain diagnostics. A terminal historical or pointer-only obsolete request never blocks a new recovery request. Once Platform reports the Service active again, METASERVICE-ADMIN can explicitly retry business synchronization; an inactive connection returns a controlled recovery message instead of being presented as a successful retry.

The complete operator matrix, Demo limitations, web-help locations and secret-free diagnostics are documented in docs/platform-integration-modes.md. Use:

./venv/bin/python bin/checks/platform_integration_mode.py

to compare the current process with configuration on disk without printing API key values.

Stage 13.7 provides the reproducible closeout harness:

./bin/check_stage13_acceptance.sh

The default matrix is zero-network and non-destructive. --live-http adds read-only Production/Testing key-status calls using the configured profile credentials without rewriting .env. Real namespace-switch evidence remains a separate superuser/restart workflow and is observed with bin/checks/integration_switch_state.py; the acceptance harness never changes the installation namespace by itself.

Matching and Platform-assisted selection

Open remains the owner of provider eligibility and assignment. When enabled, Platform may rank currently eligible local Provider identifiers through the authenticated v1/platform/matching/search/ endpoint relative to the configured Platform API root; Open then maps the result back to its own Provider rows and revalidates local eligibility before returning a handler candidate batch. Timeout, malformed response or an ineligible Platform result falls back to the existing local ordering.

The policy is controlled by:

  • PLATFORM_MATCHING_MODE=off — never request candidates from Platform; composite_only — permit this only for future composite orders; always — permit Platform candidates for ordinary and composite matching requests. A mode may use Platform only when PLATFORM_INTEGRATION=1 and the selected Production/Testing profile resolves effective PLATFORM_API_URL, PLATFORM_API_KEY and METASERVICE_ID. PLATFORM_MATCHING_API_TIMEOUT_SECONDS limits each ranking request.
  • MATCHING_CLIENT_DISFOLLOW_MODE=penalize|exclude — treatment of an active relationship from a client to a provider.
  • MATCHING_PROVIDER_DISFOLLOW_MODE=penalize|exclude — treatment of an active relationship from a provider to a client.

exclude is an Open-side hard eligibility blocker. penalize keeps the candidate eligible; a richer penalty score remains future matching evolution. Phase 2 does not let Platform override Open's effective provider/role/company/ resource/category-requirement, disfollow or runtime-availability checks.

For instance, ipd and ipt tariffs the order stores an explicit positive Orders.quantity (Decimal(12,3), default 1). The same value is used by the web/API/mobile payloads, predicted pricing and financial snapshots; other tariff types normalize quantity to 1. DEFAULT_ORDER_QUANTITY is retired.

is_global controls whether an object may be synchronized with Platform; is_visible controls whether it may participate in a future composite-chain plan. Only t is ready. Legacy o, transition states d/s and error e are fail-closed and are not considered ready.

Historical SERVICE_REQUEST cleanup

Historical service requests are archived by moving their Ticket to the terminal CLOSED status; they are not physically deleted. The maintenance command uses an exclusive local calendar boundary and runs as a dry-run unless --apply is passed:

./venv/bin/python manage.py close_service_requests_before --before 2026-08-05
./venv/bin/python manage.py close_service_requests_before --before 2026-08-05 --apply

The example selects all SERVICE_REQUEST tickets created before 2026-08-05 00:00 in the configured Django time zone. The command closes every non-terminal Ticket and also repairs stale Orders.status values for Tickets that were already CLOSED. Applied changes create audit Events; XMPP rooms are removed for every affected related order.

Launch

To start the web application, run bin/start.sh.

Immutable tariff location policy

Service.location_type is selected only while a tariff is created. Existing tariffs keep NULL; an existing tariff may never change from NULL to a value or between values. Provider offers inherit a configured tariff value, otherwise choose their own. Orders.location_type is a snapshot fixed for new orders or on first provider assignment.

Геолокация заказа через XMPP

Текущая геопозиция участников активного заказа передаётся напрямую через техническую MUC-комнату order_location. Комната создаётся только при назначенном исполнителе, включает клиента, отдельного получателя и исполнителя, не выводится как обычная беседа, не получает MUCSub-подписки и скрыта из публичного списка комнат и уничтожается общим lifecycle при CLOSED. Интервалы, радиус приблизительной позиции и точное окно публикуются из .env в mobile manifest; backend не хранит отдельные live-обновления.

GPX-трек исполнителя

При SHARIX_ORDER_LOCATION_TRACK_ENABLED=true мобильное устройство назначенного исполнителя собирает только точные точки динамического заказа, формирует полный GPX и через PUT /dbsynce/api/v1/mobile/orders/<id>/provider-track/ периодически заменяет одно специальное вложение связанного тикета. Live-location по-прежнему идёт напрямую через XMPP; координаты клиента и получателя не сохраняются. Переходы lifecycle не блокируются ошибкой загрузки: локальный журнал и final.pending остаются на устройстве до подтверждённой финальной загрузки. Финальная стоимость динамического distance-компонента берёт расстояние только из текущего вложения, отмеченного финальным upload. Незавершённый, отсутствующий или некорректный GPX не подменяется DEFAULT_ORDER_DISTANCE; такой расчёт остаётся незавершённым до reconciliation. SHARIX_ORDER_LOCATION_TRACK_MAX_SEGMENT_KM задаёт защитный предел для аномального скачка между соседними точками.

Django 5.2 runtime and rollback snapshot

The production framework baseline is Django 5.2 LTS. Before a major framework upgrade, record runtime prerequisites and publish a Git snapshot of the exact working installation:

./venv/bin/python conf/utils/runtime_inventory.py --preflight-django52
./bin/snapshot_django42_repositories.sh backup/django-4.2-final --dry-run
./bin/snapshot_django42_repositories.sh backup/django-4.2-final

The snapshot script commits and pushes pending changes in every connected first-level Git repository, publishes the named backup branch at that commit, and leaves every checkout on its original working branch.

After installing requirements, validate with:

./venv/bin/python conf/utils/runtime_inventory.py --check-django52
./venv/bin/python -Wa manage.py check
./venv/bin/python manage.py makemigrations --check --dry-run
./venv/bin/python manage.py migrate --plan

Service onboarding (Stage 9)

sharix_onboarding is an optional Open-owned module for designing and launching a service. It uses the existing ShariX Sysadmin module lifecycle (Системная панель -> Модули) and the standard bin/install.sh; Stage 9 does not introduce a second installer.

The public repository is:

https://git.sharix-app.org/ShariX_Open/sharix-open-onboarding.git

Before Stage 9.3 materialization, real-mode design is stored only under conf-real/onboarding/<plan_id>/service-plan.json with immutable revisions and does not create Company/Relationship/Permissions/ServiceCategory/Service/Provider records. Demo mode reuses the Stage 8 reference environment.

Stage 9.2 resolves semantic needs to available implementations. If an accessible module is selected but not installed, onboarding sends the administrator to the canonical Sysadmin Modules workflow. The same module configuration functions are available from the sysadmin_module management command for server automation. After configuration, ./bin/install.sh materializes source/requirements/migrations and restarts the runtime.

Module-specific configuration is discovered only from actually installed <app>.sharix_onboarding contributions. Closed/private unavailable modules remain exact-design gaps with supported fallback/defer/custom-extension choices.

Read-only validation after installation:

./venv/bin/python manage.py check_onboarding_projects

Local automated verification (post-Stage-9 Phase 3)

sharix_local_verifications is an optional private provider module for Open installations that enable it. The first provider, local_egrn_ownership, verifies Resource ownership from a linked EGRN evidence document without introducing a second checks/documents engine.

The provider is registered through the shared AutomatedVerificationProvider registry. Shared backend code never imports the optional module. Resource-specific stable identifiers are contributed through dbsynce.lib.resource_identity; Service Constructor currently contributes the cadastral number/address of its garden-plot Resource profile.

Configure an EGRN ownership CheckDefinition with automation_provider_code=local_egrn_ownership and metadata.attempt_scope=consumer. The consumer scope prevents a PASS for one Resource from satisfying a different Resource. Evidence-bound PASS checks are also invalidated when the source Document draft revision changes.

The initial parser accepts deterministic XML. Unsupported/ambiguous/redacted evidence remains PENDING for manual review; it is never converted to a synthetic FAIL. Source files stay in canonical Documents storage; RequirementCheck stores only bounded normalized facts and provenance (Document id/revision, SHA-256, provider/parser versions and reason codes).

Install/enable the module through ShariX Sysadmin and the normal bin/install.sh local-module lifecycle. The canonical private repository is:

https://git.sharix-app.org/ShariX/sharix-local-verifications.git

Optional module lifecycle (Stage 3)

Optional Django applications use one deployment contract on Open and Platform:

  • INSTALLED_APPS_LOCAL means the module is configured in the assembly;
  • SHARIX_MODULE_<APP>_ENABLED=false keeps configuration/source but removes the app from the next Django runtime;
  • runtime readiness is derived by sharix_sysadmin and never stored in a second database inventory;
  • enabled apps may expose a side-effect-free <app>.sharix_health provider;
  • missing optional modules are fail-soft, while integration/import errors of an enabled module are recorded as module-health ERROR.

Operational checks:

./venv/bin/python manage.py check_sharix_modules
./venv/bin/python manage.py check_sharix_modules --live

The default check does not contact external services. --live is explicit and may test connectivity only for providers that support it.

Shared repository maintenance

Shared nested Git checkouts can be reviewed and synchronized without changing the shell working directory or accidentally committing files to the parent webapp repository:

./bin/shared_repositories.sh status
./bin/shared_repositories.sh push
./bin/shared_repositories.sh pull

push is interactive per repository: it shows changed files and asks for that repository's commit message before committing/pushing. pull first fetches and validates every installed shared checkout, then fast-forwards only after the whole preflight succeeds. Wrong origin/branch, detached HEAD, dirty pull trees, divergence and in-progress Git operations are rejected.

Stage 7.6.6 canonical migration upgrades

Historical installations are upgraded through the validated canonical-baseline workflow documented in docs/stage7_6_6_migration_normalization.md. Do not solve migration drift on a deployment host by running makemigrations, manual SQL or --fake. Existing installation-local pre-baseline migration source is archived under conf-real/migration-legacy/; sealed baseline manifests and ordinary post-baseline migrations remain Git-owned release source.

Before a production-like upgrade, run the baseline/adoption preview and the Stage 7.6.6-B clean-install + historical-upgrade rehearsal. The final evidence is summarized with ./bin/rehearsal_acceptance.sh and is used to generate the production migration runbook.

Stage 11.4 Platform commercial policy delivery

Platform commercial policy is received through the existing authenticated PATCH v1/platform/settings/ control channel. The Service does not create a replacement service-wide commission field: the delivered effective value is materialized into the existing ServiceCategory.platform_comission for every category in the configured METASERVICE_ID namespace.

The local PlatformCommercialPolicyState table stores only delivery/version metadata and the normalized policy payload. Replaying the same Service policy version is idempotent and repairs category drift; older or conflicting versions are rejected. New categories inherit the latest delivered value through the Open assembly signal, so payment snapshots cannot observe a temporary default commission between Platform reconciliation cycles.

The same Platform->Service request may ask for the Stage 11.3 module status snapshot. This forms a narrow commercial/licensing channel that remains separate from business catalog/order/user synchronization.

Stage 11.5 standalone Platform settlement and offline policy

A Service that receives commercial policy schema v2 keeps the established ServiceCategory.platform_comission runtime commission and additionally has enough versioned history to settle Platform obligations without business sync. The policy carries private-module billing intervals, immutable monthly subscription terms by Platform policy revision, and the current versioned Platform legal/bank recipient details.

payments.PlatformCommercialSettlement is one immutable monthly Service -> Platform commercial snapshot. Transaction commission is read from existing BalanceLedgerEntry rows with entry_type=distribution_platform_income; closed-module subscriptions are added as separate settlement lines and are never represented as customer orders. The settlement issues an existing ClosingDocuments.TYPE_PAYMENT_ORDER JSON snapshot. Replaying a period returns the existing snapshot rather than recalculating it.

Monthly subscriptions use calendar-day proration: the activation day is billable and the day of final successful revoke is not ([activated, revoked)). A policy price change inside a month applies the revision effective on each billable day. The commercial channel returns every missing completed month from the first Platform commercial-policy month, so a temporarily offline Service can catch up without creating pre-policy retroactive periods.

A fully offline Service may import the exact same policy via a signed JSON package:

./venv/bin/python manage.py import_platform_commercial_policy /path/policy.json --dry-run
./venv/bin/python manage.py import_platform_commercial_policy /path/policy.json

The package uses HMAC-SHA256 with the existing PLATFORM_API_KEY; no new secret or alternative policy engine is introduced.

Контекстная справка web-интерфейса

Кнопка справки в общем shell открывает описание именно текущей страницы. Реестр находится в sharix_admin/page_help.py, page_help_modules.py и page_help_remaining.py; канонические определения терминов берутся из dbsynce/lib/help_terms.py.

Справка должна соответствовать фактическому web-сценарию и правам текущего пользователя. Общая часть не описывает скрытые действия более высокой роли. Deployment/env-настройки могут появляться в отдельном административном разделе справки только для METASERVICE-ADMIN (либо PLATFORM-ADMIN в соответствующей assembly) и никогда не содержат значения секретов. CLI-команды и серверный runbook остаются в README/docs.

Stage 9-11 help покрывает onboarding wizard, Appointments в общем shell, настройки Метасервиса, Sysadmin lifecycle/entitlement/status закрытых модулей и связанные Platform commercial-policy сценарии.

Stage 12.1 handler repository ownership freeze

Stage 12.1 does not change the running handler layout yet. The existing repository sharix-open-webservice-running remains active and keeps the Django/Python package webservice_running; only its previous monolithic responsibility is being split in later Stage 12 substages.

The audited ownership/reference baseline is documented in docs/stage12_handler_split_audit.md. From the Open installation root the non-mutating freeze check is:

./venv/bin/python webservice_running/tools/check_stage12_handler_split.py --project-root .

Existing frozen legacy references are allowed to disappear during 12.2–12.5. A new dependency on the legacy monolithic handler namespace outside the baseline is a regression. Runtime cutover to handlers_backend / handlers_examples starts only in subsequent substages.

Stage 12 handler repositories

handlers_backend/ and handlers_examples/ are independent shared checkouts. Stage 12.2 installs them in parallel with the still-active webservice_running checkout; removal of Platform webservice_running happens only at the atomic Stage 12.5 cutover.

Stage 12.3 distributed handler sources

Ready Open handlers are owned by handlers_examples; generic runtime/Blockly infrastructure is owned by handlers_backend. Optional modules publish handlers through the existing HandlerContribution manifest, and Sysadmin displays each handler source explicitly. Stage 12.5 runs standalone handlers through handlers_backend.main with the explicit handlers_examples.runtime_provider; webservice_running remains only the Open Django/webapp addon domain.

Stage 12.4 normalized the surviving webservice_running repository after handler extraction. Stage 12.5 removes its temporary handler assembly facade, migrates installation-local handler state to conf-real/handlers/, and switches systemd to the shared backend plus an explicit assembly provider. Stage 12 split audits operate on source ownership and intentionally ignore leftover ignored runtime directories such as __pycache__.

Stage 12.7 Open-only terminology rollout

Presentation terminology is an Open-only feature configured by METASERVICE-ADMIN through a versioned conf-real/terminology.json snapshot backed by the static dbsynce.lib.terminology semantic catalog. Missing/invalid profiles fall back to canonical forms; normal phrase resolution is memory-only. Platform keeps canonical labels and does not own a terminology page, middleware or delivery path. Open web uses semantic presentation helpers, Legal may show aliases only alongside canonical glossary terms, and the mobile manifest exposes the normalized snapshot for Flutter's existing per-server cache/ARB fallback path.

Stage 12.8 closeout acceptance

The Stage 12 cross-codebase closeout entry point on Open is bash bin/check_stage12_acceptance.sh. The default run verifies the handler split/cutover, Blockly provenance, distributed contributions, Open-only terminology, standalone runtime, Django/migration drift and the normal assembly audit. --full additionally runs the curated Testkit rehearsal smoke, critical UI smoke and the full Django test suite. The command is acceptance-only; it does not migrate the database or rewrite terminology.

For critical UI smoke, Stage 8 reference business fixtures are guaranteed only in the demo namespace (METASERVICE_ID=0). In that namespace --full uses strict UI fixture resolution. On a positive metaservice namespace the smoke remains read-only: Testkit first tries every matching persona user for object-bound fixtures, and if no suitable Order/Requirement ticket exists the case is reported as SKIP rather than creating production business data solely for acceptance. Real HTTP/status/template failures for resolvable cases still fail the command. Set STAGE12_UI_SMOKE_STRICT=1 to require fixture availability explicitly on a positive namespace.

Updating installation-local install.cfg

After pulling a version whose bin/install.cfg.example adds repository keys, run ./bin/configure_local_configs.sh --sync-install-cfg. The command backs up the installation-local file and appends only missing canonical keys; it does not replace deployment-specific values already present.

Compliance-critical source and proprietary capability policy

Canonical AGPL repositories include AGENTS.md, COMPLIANCE.md and COMPLIANCE.json; assembled acceptance verifies these files together with the public source-provenance boundary. Removing the current mechanism requires an equivalent fail-visible replacement, not simply deleting the guard. Private-module installation authorization is resolved centrally by Sysadmin from online Platform state, signed offline evidence, or the already-approved narrow owner-Service Git fallback. Missing/expired authorization does not delete data or disable unrelated Service functionality, and no remote heartbeat is introduced solely as DRM.

Active-order concurrency policy (Stage 18.2)

Двухуровневая настройка параллельных активных заказов Сервиса и Категорий, а также matching/activation semantics описаны в docs/order_concurrency.md.

Stage 18.3 — Order-first Legal Practice

When the optional sharix_legal_practice module is installed, Order detail discovers its neutral extension provider without a hard dependency from Open core to the closed module. LegalMatter creation/linking remains module-owned and object-level authorized. Self-order is an explicit canonical Order mode for an executor creating an Order for the same user; it does not create a fake client role and does not bypass pricing, requirements, payment or active-order concurrency.

Stabilization 0.9.1 operational prerequisites

Production-like install/update requires LDAP client tools (openldap-clients on ALT/RHEL, ldap-utils on Debian/Ubuntu), a valid TLS/certificate path to active HTTPS repositories, and a working static serving contour. bin/check_stabilization_s7_acceptance.sh verifies those host assumptions and fetches the canonical /static/sharix_admin/css/base.css asset. Proprietary optional repositories remain commented opt-in schema entries in the tracked bin/install.cfg.example; only installation-local conf-real/bin/install.cfg activates them. STATIC_SMOKE_BASE_URL is a file-only override for the HTTP smoke target.

Release 0.9.2 shared order-form contract

The canonical Open OrderForm remains the full Service-side Orders form, but its cross-assembly label/receiver/location/time normalization now inherits dbsynce.lib.order_form_contract.OrderRequestFormContractMixin. Platform uses the same shared mixin for direct-client composition instead of maintaining a second copy of Open order-form semantics.

S92 read-only stabilization diagnostics

Before S92 changes business semantics, operators can capture a credential-blind inventory with:

./venv/bin/python manage.py installation_diagnostics --json

The report uses existing source/update/runtime owners and scans tracked examples/source for requirements, env-key read-sites, CKEditor usage and handler Blockly provenance. It performs no remote refresh or repair.

S92.2 Platform synchronization recovery

The Service integration card follows the synchronization policy returned by Platform. request_allowed enables an ordinary retry, recovery_allowed identifies a synchronization-owned lifecycle error that may be recovered without a new activation request, and recovery_requested shows that recovery is already queued/running. Activation/setup errors remain on the activation workflow. See docs/s92_2_platform_sync_recovery.md.

S92.3 — category activation convergence

S92.3 makes Service and Platform category activation converge on one Platform-owned ST_REQUEST built from the same canonical approval snapshot. The Service exposes approval_data for Platform-initiated review, shows a four-state activation projection, and enforces zero Platform commission server-side when category payment is disabled. Directly sourcing bin/utils/runtime_update.sh now resolves this installation as Open without relying on caller-exported project variables.

S92.5 installation identity and S92.6 dependency constraints

SYSTEMD_SERVICE_NAME belongs to the installation-local .env. Multiple Open/Platform trees may coexist on one host and must keep distinct service/handler namespaces. Routine updates preserve the existing value and stop before systemd changes when the root env contains duplicate identities or a shell override points at a different installation.

Python convergence is owned by root constraints.txt; module requirements.txt files keep direct requirements. bin/install.sh, handler installation and dependency rehearsal install under those constraints and run pip check. A successful install writes conf-real/dependency-evidence.json with manifest hashes, Python/package versions and the successful pip check result; no secret env values are recorded. For S92.6 fresh-environment acceptance run bin/rehearsal_install_dependencies.sh --recreate-venv before the ordinary acceptance suite.

S92.7 editor-neutral rich text

CKEditor 4 is not a supported runtime dependency. LandingPage.content remains ordinary HTML in a Django TextField; TinyMCE is an admin/form widget only, and landing.rich_text owns the server-side allowlist used on save and public render. Historical Platform CKEditor migration references are migration-only compatibility evidence. Install/update must use assembly constraints, then run the S92.7 guard, Landing sanitizer/widget tests, migration drift checks and collectstatic --noinput. Student-Open intentionally keeps landing on its configured office branch; that branch owns its canonical migration graph and S92.7 advances the factual 0004_landingmainpagesettings_extra_section_title_and_more leaf with additive 0005_s92_7_editor_neutral_content. Routine update must preserve the configured Landing branch rather than substituting master.

S92.10 behavioral acceptance and runtime recovery

S92.10 turns the post-S92.9 release proof into a 14-scenario behavioral matrix. The tracked source contract is checked by ./venv/bin/python bin/checks/s92_10_behavioral_matrix.py; the canonical behavioral rehearsal is ./bin/check_s92_10_behavioral_matrix.sh. Add --live-runtime only when the current host is expected to have functional handlers. Fresh dependency recreation is destructive to the current venv and is therefore rehearsal-only: set SHARIX_S92_10_ALLOW_VENV_RECREATE=1 and add --fresh-dependencies only on a disposable/rehearsal installation.

OPERATIONAL_BRANCH is the normal branch selector. Commented repository-specific examples such as # DESIGN_TEMPLATE_BRANCH=... are optional overrides and are not required in installation-local install.cfg; an active override remains authoritative.

If a namespaced handler template still points to another historical checkout while the main service of the same namespace belongs to the current installation, repair it explicitly with ./bin/install_handlers.sh --repair-unit-link. Default installation stays fail-closed. The repair backs up/removes only the stale systemd symlink and does not delete the old checkout's target file.

API-key setup and client-card usability

Visual Settings / Application Settings shows configured API tokens for the existing admitted HF, Ferma and Russian Post API fields as text to superusers. LDAP/acquiring passwords remain password fields. Empty generic secret fields retain their existing value; saving other settings must not clear credentials. Open this editor only in a private administrative session and exclude its values from screenshots or support reports. Its errors do not echo persistence exceptions.

Platform Production/Testing credentials already belong to the separate Metaservice Environment / Application Settings page. The Visual Settings editor links there rather than adding duplicate profile keys. Paste a key issued by the same Platform as the selected API URL and Metaservice ID. Save and use the existing coordinated restart action before the explicit connection check. API keys remain visible there and use the shared visible-text copy component.

Client corporate actions wrap within the card at narrow widths. Existing eligibility, representative requests, payments and profile-sync rules are not changed. The touched page chrome/help is RU/EN; user-authored content is unchanged.

This change has no migrations or environment normalization. Recompile only the affected catalogs, publish owning sources, run collectstatic and restart the installation's verified app unit. No test database is required by this patch.

The source-publication policy guard reads repository declarations from bin/utils/repository_catalog.sh, the current catalogue owner, rather than searching the caller script for the retired inline table. License/provenance requirements and failure behavior are unchanged.