simbiot-harness/artifacts/pvt-blockchain-constitution-demo.html

205 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Конституция кооператива на блокчейне — интерактивное демо для ПВТ</title>
<style>
:root{--ink:#0d1117;--bg:#0a0e14;--panel:#11161f;--panel2:#161d29;--line:#232c3b;--mut:#8b96a8;--acc:#4d8dff;--acc2:#22c55e;--warn:#f59e0b;--bad:#ef4444;--vio:#a78bfa}
*{box-sizing:border-box}
body{margin:0;font-family:'SF Mono','Cascadia Code',Consolas,monospace;background:var(--bg);color:#dbe2ee;font-size:14.5px;line-height:1.6}
.wrap{max-width:1060px;margin:0 auto;padding:28px 18px 90px}
header{border:1px solid var(--line);border-radius:14px;padding:22px 26px;margin-bottom:22px;background:linear-gradient(135deg,#101726,#0d1420)}
.kicker{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--acc);font-weight:700}
h1{margin:8px 0 6px;font-size:26px;line-height:1.25}
.sub{color:var(--mut);font-size:13px}
.cols{display:grid;grid-template-columns:300px 1fr;gap:18px}
@media(max-width:860px){.cols{grid-template-columns:1fr}}
.panel{background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden}
.panel h3{margin:0;padding:12px 16px;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--mut);border-bottom:1px solid var(--line);background:var(--panel2)}
.pbody{padding:14px 16px}
.member{display:flex;align-items:center;gap:10px;padding:9px 10px;border:1px solid var(--line);border-radius:10px;margin:8px 0;background:var(--panel2);cursor:pointer;transition:border-color .15s}
.member:hover{border-color:var(--acc)}
.member.sel{border-color:var(--acc);box-shadow:0 0 0 1px var(--acc) inset}
.avatar{width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:#fff}
.mname{font-weight:700;font-size:13.5px}
.mrole{font-size:11px;color:var(--mut)}
.voteweight{margin-left:auto;font-size:11px;color:var(--vio)}
.ledger{background:#080b10;border-radius:10px;border:1px solid var(--line);padding:12px;max-height:340px;overflow-y:auto;font-size:12px}
.tx{border-left:2px solid var(--acc2);padding:6px 10px;margin:7px 0;background:#0c121b;border-radius:0 8px 8px 0}
.tx.gov{border-left-color:var(--vio)}
.tx.peg{border-left-color:var(--acc)}
.tx.err{border-left-color:var(--bad)}
.txhead{display:flex;justify-content:space-between;gap:8px;font-weight:700;color:#e8eefb;font-size:11.5px}
.txbody{color:var(--mut);margin-top:3px;white-space:pre-wrap}
.ok{color:var(--acc2);font-weight:700}.warn{color:var(--warn);font-weight:700}.err{color:var(--bad);font-weight:700}.vio{color:var(--vio)}
.btnrow{display:flex;flex-wrap:wrap;gap:10px;margin:14px 0}
button{font-family:inherit;font-size:12.5px;font-weight:700;padding:10px 14px;border-radius:10px;border:1px solid var(--acc);background:#15243f;color:#bcd6ff;cursor:pointer;transition:.15s}
button:hover{background:#1b3157}
button:disabled{opacity:.35;cursor:not-allowed}
button.ghost{border-color:var(--line);background:var(--panel2);color:var(--mut)}
.kv{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;font-size:12.5px}
.kv b{color:var(--mut);font-weight:400}
.bar{height:10px;background:#0b1119;border:1px solid var(--line);border-radius:99px;overflow:hidden;display:flex}
.seg{height:100%}
.legend{display:flex;flex-wrap:wrap;gap:12px;font-size:11px;color:var(--mut);margin-top:8px}
.dot{display:inline-block;width:9px;height:9px;border-radius:3px;margin-right:5px;vertical-align:-1px}
.note{background:#101726;border:1px solid var(--line);border-radius:10px;padding:12px 14px;font-size:12px;color:var(--mut);margin-top:12px}
.note b{color:#c8d4e6}
.sec2{margin-top:22px}
.timeline{display:grid;gap:10px}
.step{display:grid;grid-template-columns:34px 1fr;gap:12px;align-items:start}
.n{width:30px;height:30px;border-radius:9px;background:#15243f;border:1px solid var(--acc);color:#bcd6ff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px}
.step .t{font-weight:700;font-size:13.5px}
.step .d{color:var(--mut);font-size:12.5px}
footer{margin-top:34px;border-top:1px solid var(--line);padding-top:14px;font-size:11.5px;color:var(--mut)}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="kicker">Кооператив 42 · Интерактивное демо для ПВТ</div>
<h1>Конституция кооператива на блокчейне</h1>
<div class="sub">Как устав и законы кооператива исполняются on-chain: голосование → решение → юридическое действие. Смарт-контракт — исполнительный механизм, устав — источник власти (ГК РБ + Декрет №8). Основа контента: док законов t-261014120323.</div>
</header>
<div class="cols">
<div>
<div class="panel">
<h3>Реестр членов</h3>
<div class="pbody">
<div class="kv" style="margin-bottom:10px"><b>Всего членов:</b><span id="mcount">—</span></div>
<div id="members"></div>
<div class="note" style="margin-top:10px">Каждый член — адрес в реестре. <b>1 член = 1 голос</b> (§111 WY / устав). Кликните — проголосовать от имени члена.</div>
</div>
</div>
<div class="panel" style="margin-top:16px">
<h3>Смарт-контракт</h3>
<div class="pbody">
<div class="kv">
<b>Адрес:</b><span>0x42…C0NF (в уставе)</span>
<b>Версия:</b><span id="cver">v1.0</span>
<b>Кворум:</b><span id="cq">—</span>
<b>Порог:</b><span>50%+1 от голосовавших</span>
<b>Upgradable:</b><span class="ok">да, dual-confirm</span>
</div>
<div class="note">Публичный адрес контракта фиксируется в уставе (аналог §109 WY: неактуальный идентификатор блокирует on-chain операции).</div>
</div>
</div>
</div>
<div>
<div class="panel">
<h3>Активное предложение (on-chain governance)</h3>
<div class="pbody">
<div id="proposal" class="tx gov"><div class="txhead"><span>PROPOSAL-1 · governance</span><span id="pstate">открыто</span></div><div class="txbody">Принять Конституцию кооператива v1: цифровой режим управления, учёт паёв в токенах, решения органов оформляются on-chain.</div></div>
<div style="margin:12px 0 6px;font-size:12px;color:var(--mut)">Явка / кворум ⅔</div>
<div class="bar" id="bar"></div>
<div class="legend">
<span><span class="dot" style="background:#22c55e"></span>За</span>
<span><span class="dot" style="background:#ef4444"></span>Против</span>
<span><span class="dot" style="background:#232c3b"></span>Не голосовали</span>
<span id="tally" style="margin-left:auto"></span>
</div>
<div class="btnrow">
<button id="btnVote" onclick="castVote()">Проголосовать (за)</button>
<button class="ghost" onclick="castVote(true)">Против</button>
<button id="btnExec" onclick="executeProposal()" disabled>Исполнить решение</button>
<button class="ghost" onclick="location.reload()">Сброс демо</button>
</div>
<div id="verdict" class="note">Выберите члена слева и проголосуйте. Когда явка достигнет кворума и большинство — «за», кнопка «Исполнить решение» активируется: смарт-контракт оформит решение собрания on-chain.</div>
</div>
</div>
<div class="panel" style="margin-top:16px">
<h3>Журнал реестра (ledger)</h3>
<div class="ledger" id="ledger">
<div class="tx peg"><div class="txhead"><span>GENESIS · peg</span><span>#0</span></div><div class="txbody">Реестр привязан к уставу кооператива (РБ): состав органов, паи, правила — из юрдокумента. Токен = учёт пая, не ценная бумага (Декрет №8).</div></div>
</div>
</div>
</div>
</div>
<div class="panel sec2">
<h3>Как решение становится юридическим фактом (5 шагов)</h3>
<div class="pbody timeline">
<div class="step"><div class="n">1</div><div><div class="t">Предложение (proposal)</div><div class="d">Правление вносит предложение on-chain. В уставе закреплено: повестка собрания = активные предложения реестра.</div></div></div>
<div class="step"><div class="n">2</div><div><div class="t">Голосование членов (1 член = 1 голос)</div><div class="d">Члены голосуют подписью со своего адреса. Тайна личности — псевдонимизация, вес — по уставу, не по капиталу.</div></div></div>
<div class="step"><div class="n">3</div><div><div class="t">Кворум + порог</div><div class="d">Смарт-контракт считает явку и голоса по уставным параметрам (здесь: кворум ⅔, порог 50%+1). Невозможность «накрутки» — математика реестра.</div></div></div>
<div class="step"><div class="n">4</div><div><div class="t">Исполнение (execute)</div><div class="d">Контракт оформляет решение операцией в реестре; для решений, требующих юрдействия (реестр юрлиц, договоры), формируется пакет для подписи председателем — принцип «контракт исполняет, устав властвует».</div></div></div>
<div class="step"><div class="n">5</div><div><div class="t">Прозрачность (audit)</div><div class="d">Любой партнёр (ПВТ, аудит, член) проверяет историю голосований и решений в открытом реестре — без запроса отчётности (§112 WY).</div></div></div>
</div>
</div>
<div class="panel sec2">
<h3>Привязка к праву РБ (для юристов ПВТ)</h3>
<div class="pbody" style="font-size:13px">
<ul style="margin:0;padding-left:18px;color:#c3cddd">
<li><b>Юрлицо:</b> производственный кооператив (ГК РБ, ст. 104–113) — устав обязателен, собрание — высший орган.</li>
<li><b>Цифровой слой:</b> Декрет №8 «О развитии цифровой экономики» — токены (учёт пая), смарт-контракты (оформление сделок/решений), резидентство ПВТ.</li>
<li><b>Иерархия:</b> устав выше контракта — реестр признаётся доказательством состояний, контракт — исполнительный механизм; коллизии решает собрание.</li>
<li><b>Защита членов:</b> выход — с выплатой пая (обязательна); контрактом это автоматизируется, но не отменяется.</li>
</ul>
</div>
</div>
<footer>Демо-симуляция работы Конституции кооператива on-chain · Кооператив 42 · артефакт t-261014121824-a70757 · контент по док законов РБ (t-261014120323) · не юрзаключение, для показа продукта партнёрам ПВТ.</footer>
</div>
<script>
const MEMBERS=[
{n:'Алекс',r:'председатель / продукт',c:'#4d8dff'},
{n:'Юра',r:'правление / операции',c:'#22c55e'},
{n:'Марина',r:'финансы и договоры',c:'#f59e0b'},
{n:'Дима',r:'инженерия',c:'#a78bfa'},
{n:'Стас',r:'партнёрства',c:'#ef4444'},
{n:'Наталья',r:'юрист-консультант',c:'#14b8a6'}
];
let sel=null, votes={}, done=false, ntx=0;
const QUORUM=Math.ceil(MEMBERS.length*2/3); // ⅔
function $(id){return document.getElementById(id)}
function log(kind,head,body){ntx++;const d=document.createElement('div');d.className='tx '+kind;d.innerHTML='<div class="txhead"><span>'+head+'</span><span>#'+ntx+'</span></div><div class="txbody">'+body+'</div>';$('ledger').prepend(d)}
function renderMembers(){
$('mcount').textContent=MEMBERS.length+' (3 физлица минимум по ГК — норма соблюдена)';
$('members').innerHTML=MEMBERS.map((m,i)=>'<div class="member'+(sel===i?' sel':'')+'" onclick="pick('+i+')"><div class="avatar" style="background:'+m.c+'">'+m.n[0]+'</div><div><div class="mname">'+m.n+'</div><div class="mrole">'+m.r+'</div></div><div class="voteweight">1 голос</div></div>').join('');
}
function pick(i){sel=i;renderMembers();log('peg','SELECT_SIGNER','подписант: '+MEMBERS[i].n+' ('+MEMBERS[i].r+') — голос будет подписан адресом члена')}
function renderVotes(){
const v=MEMBERS.map((m,i)=>votes[i]);
const yes=v.filter(x=>x===true).length,no=v.filter(x=>x===false).length,abst=MEMBERS.length-yes-no;
$('bar').innerHTML='<div class="seg" style="width:'+(yes/MEMBERS.length*100)+'%;background:#22c55e"></div><div class="seg" style="width:'+(no/MEMBERS.length*100)+'%;background:#ef4444"></div>';
$('tally').innerHTML='<span class="ok">'+yes+' за</span> · <span class="err">'+no+' против</span> · '+abst+' молчат';
const turnout=yes+no;
$('cq').textContent=turnout+'/'+MEMBERS.length+' (нужно '+QUORUM+')';
const q=turnout>=QUORUM, pass=q&&yes>no;
if(!done){
$('btnExec').disabled=!pass;
$('pstate').innerHTML=pass?'<span class="ok">кворум есть · большинство ЗА</span>':'<span class="warn">ждёт голосов</span>';
if(pass)$('verdict').innerHTML='<b>Кворум достигнут, большинство — за.</b> Нажмите «Исполнить решение»: смарт-контракт оформит решение собрания операцией в реестре (шаг 4).';
else $('verdict').innerHTML='Явка '+(turnout)+' из '+MEMBERS.length+', кворум '+QUORUM+'. Голосуйте от имени разных членов (клик слева → кнопка).';
}
}
function castVote(against){
if(done){log('err','ERROR','предложение уже исполнено — реестр неизменяем');return}
if(sel===null){log('err','ERROR','выберите члена в реестре слева');return}
if(votes[sel]!==undefined){log('err','REJECT','двойной голос отклонён: адрес '+MEMBERS[sel].n+' уже голосовал (анти-манипуляция реестра)');return}
votes[sel]=!against;
log('gov','VOTE',''+MEMBERS[sel].n+' → '+(against?'ПРОТИВ':'ЗА')+' · подпись адреса принята');
renderVotes();
}
function executeProposal(){
const yes=Object.values(votes).filter(x=>x).length;
if($('btnExec').disabled){log('err','EXECUTE_REJECT','условия устава не выполнены (кворум/порог)');return}
done=true;
$('pstate').innerHTML='<span class="ok">ИСПОЛНЕНО</span>';
log('gov','EXECUTE','решение собрания оформлено: Конституция v1 принята ('+yes+' за, кворум '+QUORUM+') · запись реестра = протокол собрания');
log('peg','LEGAL_BRIDGE','сформирован пакет юрдействий: протокол для подписи председателем, ссылка на запись реестра — устав выше контракта, контракт его исполняет');
$('verdict').innerHTML='<b>Готово.</b> Решение зафиксировано в реестре (неизменяемо), юрпакет передан на подпись. Дальше по дорожной карте: юристы ПВТ → резидентство → устав с «цифровым режимом» → dual-running пилот.';
$('btnVote').disabled=true;$('btnExec').disabled=true;
}
renderMembers();renderVotes();
</script>
</body>
</html>