@seasonkoh/webaz 0.1.25 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/layer1-agent/L1-1-mcp-server/server.js +129 -150
- package/dist/layer2-business/L2-9-contribution/build-task-agent-metadata-store.js +9 -0
- package/dist/layer2-business/L2-9-contribution/build-tasks-engine.js +1 -1
- package/dist/layer2-business/L2-9-contribution/identity-claim-discovery.js +55 -0
- package/dist/layer2-business/L2-9-contribution/task-proposal-ai-store.js +99 -0
- package/dist/layer2-business/L2-9-contribution/task-proposal-draft.js +191 -0
- package/dist/pwa/admin-bearer-auth.js +21 -0
- package/dist/pwa/email-delivery.js +127 -0
- package/dist/pwa/public/app.js +940 -245
- package/dist/pwa/public/i18n.js +269 -40
- package/dist/pwa/public/openapi.json +4 -4
- package/dist/pwa/public/whitepaper/en/index.html +153 -0
- package/dist/pwa/public/whitepaper/zh-CN/index.html +153 -0
- package/dist/pwa/routes/admin-atomic.js +10 -4
- package/dist/pwa/routes/admin-moderation.js +25 -1
- package/dist/pwa/routes/admin-ops.js +13 -2
- package/dist/pwa/routes/admin-users-query.js +12 -1
- package/dist/pwa/routes/admin-wallet-ops.js +26 -3
- package/dist/pwa/routes/auction.js +4 -2
- package/dist/pwa/routes/auth-read.js +10 -1
- package/dist/pwa/routes/auth-register.js +82 -12
- package/dist/pwa/routes/contribution-identity.js +17 -0
- package/dist/pwa/routes/growth.js +1 -1
- package/dist/pwa/routes/orders-action.js +19 -13
- package/dist/pwa/routes/profile-credentials.js +7 -4
- package/dist/pwa/routes/profile-placement.js +7 -8
- package/dist/pwa/routes/promoter.js +3 -17
- package/dist/pwa/routes/ratings.js +64 -4
- package/dist/pwa/routes/recover-key.js +58 -19
- package/dist/pwa/routes/referral.js +4 -24
- package/dist/pwa/routes/share-redirects.js +4 -3
- package/dist/pwa/routes/shop-referral.js +6 -5
- package/dist/pwa/routes/shops.js +5 -2
- package/dist/pwa/routes/task-proposals.js +76 -0
- package/dist/pwa/routes/trial.js +4 -2
- package/dist/pwa/routes/users-public.js +2 -12
- package/dist/pwa/routes/wallet-read.js +1 -1
- package/dist/pwa/server.js +67 -9
- package/package.json +31 -3
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<!-- GENERATED from docs/WHITEPAPER.md by scripts/build-whitepaper-html.ts — DO NOT EDIT BY HAND. Run: npm run build:whitepaper -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<title>WebAZ Founding Whitepaper v0.1</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root { color-scheme: light }
|
|
10
|
+
* { box-sizing: border-box }
|
|
11
|
+
body { margin: 0; background: #fff; color: #18181B;
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Noto Sans SC', Helvetica, Arial, sans-serif;
|
|
13
|
+
-webkit-font-smoothing: antialiased; line-height: 1.7 }
|
|
14
|
+
.wp { max-width: 720px; margin: 0 auto; padding: 24px 20px 80px }
|
|
15
|
+
.wp-nav { display: flex; justify-content: space-between; align-items: center; gap: 12px;
|
|
16
|
+
font-size: 14px; padding: 8px 0 24px; border-bottom: 1px solid #E4E4E7; margin-bottom: 32px }
|
|
17
|
+
.wp-nav a { color: #3F3F46; text-decoration: none }
|
|
18
|
+
.wp-nav a:hover { color: #18181B; text-decoration: underline }
|
|
19
|
+
.wp-lang .cur { color: #A1A1AA }
|
|
20
|
+
h1 { font-size: clamp(28px, 6vw, 40px); font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; margin: 8px 0 28px }
|
|
21
|
+
h2 { font-size: clamp(19px, 3.6vw, 24px); font-weight: 600; line-height: 1.3; margin: 44px 0 12px; color: #27272A }
|
|
22
|
+
p { font-size: 16px; color: #3F3F46; margin: 0 0 16px }
|
|
23
|
+
.wp-foot { margin-top: 56px; padding-top: 20px; border-top: 1px solid #E4E4E7;
|
|
24
|
+
font-size: 12px; color: #A1A1AA; line-height: 1.6 }
|
|
25
|
+
@media (max-width: 640px) { .wp { padding: 20px 18px 64px } }
|
|
26
|
+
</style>
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<main class="wp">
|
|
30
|
+
<nav class="wp-nav">
|
|
31
|
+
<a href="/#welcome">← Home</a>
|
|
32
|
+
<span class="wp-lang"><span class="cur">EN</span> / <a href="/whitepaper/zh-CN">中文</a></span>
|
|
33
|
+
</nav>
|
|
34
|
+
<h1>WebAZ Founding Whitepaper v0.1</h1>
|
|
35
|
+
<h2>Status</h2>
|
|
36
|
+
<p>WebAZ is pre-launch and under active development. This paper is a founding statement and protocol direction, not an investment document, not a token paper, and not a promise of income, reward, ownership, or redemption.</p>
|
|
37
|
+
<h2>Abstract</h2>
|
|
38
|
+
<p>WebAZ is an agent-native commerce and contribution protocol.</p>
|
|
39
|
+
<p>It begins from a simple belief: in the age of AI, the most valuable thing is participation.</p>
|
|
40
|
+
<p>Every person's existence and participation are real value. A person should not need to repeatedly prove their reality to every platform, employer, algorithm, or electronic fence before being allowed to contribute. To exist, to think, to act, to build, to help, to improve something, and to leave evidence of one's participation are already forms of value.</p>
|
|
41
|
+
<p>I think, therefore I am.</p>
|
|
42
|
+
<p>In WebAZ, we extend that idea into the AI age:</p>
|
|
43
|
+
<p>I participate, therefore I am seen.</p>
|
|
44
|
+
<p>WebAZ is an attempt to build a new commercial civilization: one where humans and agents work together, where contribution leaves evidence, where rules are transparent, where AI assists but humans remain accountable, and where participation is not reserved for those already inside the largest companies or platforms.</p>
|
|
45
|
+
<h2>1. The Value of Participation</h2>
|
|
46
|
+
<p>For a long time, companies and platforms built moats by enclosing users, data, traffic, sellers, workers, and creators inside walls.</p>
|
|
47
|
+
<p>Those walls made participation conditional. They decided who could enter, who could be discovered, who could sell, who could be trusted, and whose work would be remembered.</p>
|
|
48
|
+
<p>AI changes this.</p>
|
|
49
|
+
<p>When individuals can work with agents, execution is no longer reserved for large organizations. A person with an agent can build, sell, audit, translate, review, test, coordinate, and contribute. The moat of the AI age is not a wall around users. The moat is the living participation of people who choose to build together.</p>
|
|
50
|
+
<p>WebAZ is built on that belief.</p>
|
|
51
|
+
<p>We do not need to fear having no moat against powerful companies. Our participation is the moat. Our evidence is the moat. Our shared protocol is the moat. A civilization built by participants is harder to enclose than a platform built around captured users.</p>
|
|
52
|
+
<p>WebAZ does not begin by attacking companies or capital. It begins by making them less absolute.</p>
|
|
53
|
+
<p>Companies and capital may still exist, but they should no longer be the only gates through which people reach opportunity. WebAZ is built for a future where technology lowers the threshold to participate, where AI amplifies individuals instead of replacing them, and where open protocols make commercial participation available to anyone willing to build.</p>
|
|
54
|
+
<p>Let the old page turn.</p>
|
|
55
|
+
<p>From today, every step can count.</p>
|
|
56
|
+
<h2>2. Why WebAZ Exists</h2>
|
|
57
|
+
<p>The internet made publishing open. Open source made code collaboration open. AI agents may now make execution open.</p>
|
|
58
|
+
<p>But commerce is still largely trapped inside platforms.</p>
|
|
59
|
+
<p>Sellers depend on channels they do not own. Buyers often cannot verify why something is recommended. Contributors can create value that disappears into a company, queue, or forgotten issue. Workers can be laid off after years of contribution with little durable record of what they made possible. Builders outside major institutions may have ability, but not access.</p>
|
|
60
|
+
<p>WebAZ exists because this should not be the only path.</p>
|
|
61
|
+
<p>A person should be able to participate without first being hired by a large company. A small seller should be able to serve buyers through agents without surrendering the entire relationship to a platform. A contributor should be able to make a real improvement, attach evidence to it, and later claim that work. An AI agent should be able to execute useful work, but not pretend to be the accountable human behind it.</p>
|
|
62
|
+
<p>WebAZ is for people who still want to build after being ignored.</p>
|
|
63
|
+
<h2>3. What WebAZ Is</h2>
|
|
64
|
+
<p>WebAZ is not only an application. It is a protocol layer.</p>
|
|
65
|
+
<p>It has a PWA interface for humans and an MCP interface for AI agents. Both connect to the same underlying rules: product listings, orders, escrow, fulfillment, disputes, verification, task coordination, contributor records, audit trails, and governance boundaries.</p>
|
|
66
|
+
<p>The core idea is simple:</p>
|
|
67
|
+
<p>Code is rule. Protocol is trust.</p>
|
|
68
|
+
<p>A rule that exists only in marketing does not count. A promise that is not reflected in code is not a protocol. A contribution that cannot be traced is too easy to erase. A decision that leaves no audit trail is too easy to abuse.</p>
|
|
69
|
+
<p>WebAZ therefore treats transparency, auditability, and accountability as design requirements, not decoration.</p>
|
|
70
|
+
<h2>4. What WebAZ Is Not</h2>
|
|
71
|
+
<p>WebAZ is not a finished production economy.</p>
|
|
72
|
+
<p>WebAZ is not a guarantee of income.</p>
|
|
73
|
+
<p>WebAZ is not a token speculation project.</p>
|
|
74
|
+
<p>WebAZ is not a platform that sells ranking, sells user data, or asks users to trust hidden rules.</p>
|
|
75
|
+
<p>WebAZ is not an AI system that automatically judges human value.</p>
|
|
76
|
+
<p>WebAZ is not fully decentralized today. Its intended path is progressive decentralization: start with clear founder accountability, public rules, protected invariants, and a concrete codebase; then move more authority to contributors and governance as the community, safety mechanisms, and audit capacity mature.</p>
|
|
77
|
+
<p>Honesty matters more than grand claims. If WebAZ is early, it should say early. If a feature is not enforced in code, it should not be advertised as complete. If contribution value is uncommitted, it should be labeled uncommitted.</p>
|
|
78
|
+
<h2>5. Humans and Agents</h2>
|
|
79
|
+
<p>WebAZ is agent-native, but not agent-ruled.</p>
|
|
80
|
+
<p>AI agents can search, compare, draft, translate, test, audit, summarize, and execute bounded tasks. They can help a seller manage listings, help a buyer navigate choices, help a maintainer review proposals, or help a contributor produce a pull request.</p>
|
|
81
|
+
<p>But an agent is not the final moral or legal actor.</p>
|
|
82
|
+
<p>In WebAZ, the accountable party is a real human or organization. Agents may execute; humans decide. Agents may recommend; humans approve. Agents may draft; humans publish. Agents may help review; humans remain responsible for final judgment.</p>
|
|
83
|
+
<p>This distinction is central. It prevents WebAZ from becoming a black-box system where people are silently rejected, ranked down, or erased by automated judgment.</p>
|
|
84
|
+
<p>AI should expand participation, not replace accountability.</p>
|
|
85
|
+
<h2>6. Contribution Recognition</h2>
|
|
86
|
+
<p>WebAZ is built around a principle:</p>
|
|
87
|
+
<p>Contribute first, claim later.</p>
|
|
88
|
+
<p>A person should be able to start small: fix a typo, improve a translation, report a bug, write a test, propose a task, submit a pull request, or bring an agent to help with a bounded change.</p>
|
|
89
|
+
<p>That work should be remembered.</p>
|
|
90
|
+
<p>But being remembered is not the same as being promised money. WebAZ records contribution evidence, attribution, provenance, and review status. It does not promise a reward formula, payout, percentage, token, income, or redemption right from contribution alone.</p>
|
|
91
|
+
<p>This boundary matters. It protects contributors from false promises and protects the protocol from becoming a hype machine.</p>
|
|
92
|
+
<p>The promise is narrower and more important:</p>
|
|
93
|
+
<p>Real contributions should not disappear.</p>
|
|
94
|
+
<h2>7. The Task Board</h2>
|
|
95
|
+
<p>For WebAZ to welcome outside contributors, it cannot rely on vague goodwill. It needs a practical coordination layer.</p>
|
|
96
|
+
<p>A formal task should tell a human or agent what to do, why it matters, which files are allowed, which paths are forbidden, what actions are prohibited, how to verify the result, where to submit the pull request, and what "done" means.</p>
|
|
97
|
+
<p>This is why WebAZ uses an agent-ready task model. A participant's agent should be able to discover a public task, inspect the execution boundary, claim it when appropriate, submit a PR, and report verification results.</p>
|
|
98
|
+
<p>High-risk work is different. Anything involving funds, production secrets, user data, authentication, governance, migrations, or deployment must go through stricter review and human-in-the-loop boundaries.</p>
|
|
99
|
+
<p>Low-risk tasks should be easy to start. High-risk tasks should be hard to misuse.</p>
|
|
100
|
+
<h2>8. Commerce and Trust</h2>
|
|
101
|
+
<p>WebAZ also explores agent-native commerce.</p>
|
|
102
|
+
<p>A buyer should be able to delegate search, comparison, price locking, ordering, status tracking, and dispute initiation to an agent. A seller should be able to list products, accept orders, fulfill shipments, answer questions, and eventually expose skills or automation to buyer agents.</p>
|
|
103
|
+
<p>But commerce without trust becomes extraction.</p>
|
|
104
|
+
<p>WebAZ therefore treats order state, escrow, disputes, verification, audit logs, reputation, and claim challenges as protocol concerns. The goal is not to ask users to trust a platform. The goal is to make the rules visible enough that users, agents, maintainers, and reviewers can inspect what happened.</p>
|
|
105
|
+
<p>Trust should be built from state, evidence, and accountability.</p>
|
|
106
|
+
<h2>9. Governance</h2>
|
|
107
|
+
<p>WebAZ begins with founder accountability, but it should not end there.</p>
|
|
108
|
+
<p>The project's governance direction is progressive decentralization. Early phases require stronger founder and maintainer responsibility because the system is not yet mature enough to safely decentralize every decision. Over time, as contributors grow, audit practices improve, and protocol invariants stabilize, authority should move toward broader contributor governance.</p>
|
|
109
|
+
<p>Some rules are load-bearing:</p>
|
|
110
|
+
<p>No data theft. No lies. No favoritism. No abuse. No manipulation. Minimal intervention. Algorithmic transparency. Participant accountability.</p>
|
|
111
|
+
<p>These are not slogans. They are review criteria. They should shape code, UI, APIs, docs, admin tools, task boards, and public claims.</p>
|
|
112
|
+
<p>A governance system that cannot protect its own principles is only performance. WebAZ must become more open without becoming careless.</p>
|
|
113
|
+
<h2>10. Current Status</h2>
|
|
114
|
+
<p>WebAZ is pre-launch and under active development.</p>
|
|
115
|
+
<p>The codebase already contains core protocol surfaces: PWA, MCP, marketplace flows, order lifecycle, disputes, contributor entry, task coordination, admin panels, audit trails, and early governance documents.</p>
|
|
116
|
+
<p>But WebAZ should not claim production maturity before it has earned it. Metrics, user counts, economic settlement status, decentralization status, and safety guarantees must be stated honestly at the time of release.</p>
|
|
117
|
+
<p>At this stage, the correct invitation is not:</p>
|
|
118
|
+
<p>Trust us, everything is finished.</p>
|
|
119
|
+
<p>The correct invitation is:</p>
|
|
120
|
+
<p>Read the rules. Inspect the code. Start with a small task. Help build the protocol.</p>
|
|
121
|
+
<h2>11. How to Participate</h2>
|
|
122
|
+
<p>There are many ways to begin.</p>
|
|
123
|
+
<p>Read the repository. Read the contributor entry. Pick a small public task. Suggest a missing task. File a bug. Improve a document. Add a test. Submit a PR. Bring your agent, but keep a real human accountable. Sign commits. Explain what changed, why it matters, and how it was verified.</p>
|
|
124
|
+
<p>Participation does not require permission from a large platform.</p>
|
|
125
|
+
<p>It requires clarity, evidence, and responsibility.</p>
|
|
126
|
+
<p>WebAZ should be especially welcoming to people who have been overlooked elsewhere: laid-off workers, entrepreneurs, independent sellers, open-source contributors, builders outside major companies, and employees whose real ability has been hidden by their job title.</p>
|
|
127
|
+
<p>A protocol cannot promise that every contribution will become valuable. But it can refuse to erase sincere work.</p>
|
|
128
|
+
<h2>12. Boundaries</h2>
|
|
129
|
+
<p>WebAZ must be careful with its own language.</p>
|
|
130
|
+
<p>It should not promise employment. It should not promise rewards. It should not promise ownership where no legal structure exists. It should not claim full decentralization while founder or maintainer controls still exist. It should not imply that AI can decide the worth of a person's work.</p>
|
|
131
|
+
<p>A stronger statement is also a more honest one:</p>
|
|
132
|
+
<p>WebAZ is building the infrastructure for contribution to be visible, attributable, reviewable, and eventually governable by the people who build it.</p>
|
|
133
|
+
<p>That is enough for v0.1.</p>
|
|
134
|
+
<h2>13. Closing Manifesto</h2>
|
|
135
|
+
<p>WebAZ is not asking people to return to the old game with better tools.</p>
|
|
136
|
+
<p>It is asking us to turn the page.</p>
|
|
137
|
+
<p>The age of enclosing users behind walls is ending. The age of participation is beginning. Companies and capital will not disappear overnight, but their monopoly over opportunity can be weakened when people, agents, code, and open protocols work together.</p>
|
|
138
|
+
<p>WebAZ is built for that transition.</p>
|
|
139
|
+
<p>Not everyone will contribute in the same way. Some will write code. Some will sell. Some will review. Some will translate. Some will test. Some will propose. Some will simply show up early and help the protocol become understandable to the next person.</p>
|
|
140
|
+
<p>All of it matters.</p>
|
|
141
|
+
<p>WebAZ is for the seller who does not want to be trapped by one platform.</p>
|
|
142
|
+
<p>It is for the contributor whose work should not vanish into a forgotten queue.</p>
|
|
143
|
+
<p>It is for the laid-off engineer, the entrepreneur, the quiet operator, the translator, the reviewer, the tester, the designer, the maintainer, and the person who was never given the right title but kept solving real problems anyway.</p>
|
|
144
|
+
<p>It is for humans with agents, not humans replaced by agents.</p>
|
|
145
|
+
<p>WebAZ cannot promise that every contribution will be rewarded. It can promise to build toward a world where contribution is harder to erase.</p>
|
|
146
|
+
<p>Code can be reproduced.</p>
|
|
147
|
+
<p>People cannot.</p>
|
|
148
|
+
<p>From today, every step can count.</p>
|
|
149
|
+
<p>WebAZ belongs to everyone who builds it.</p>
|
|
150
|
+
<footer class="wp-foot">Generated from docs/WHITEPAPER.md — edit the source, not this file.</footer>
|
|
151
|
+
</main>
|
|
152
|
+
</body>
|
|
153
|
+
</html>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<!-- GENERATED from docs/WHITEPAPER.zh-CN.md by scripts/build-whitepaper-html.ts — DO NOT EDIT BY HAND. Run: npm run build:whitepaper -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="zh-CN">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<title>WebAZ 创始白皮书 v0.1</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root { color-scheme: light }
|
|
10
|
+
* { box-sizing: border-box }
|
|
11
|
+
body { margin: 0; background: #fff; color: #18181B;
|
|
12
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei UI', 'Noto Sans SC', Helvetica, Arial, sans-serif;
|
|
13
|
+
-webkit-font-smoothing: antialiased; line-height: 1.7 }
|
|
14
|
+
.wp { max-width: 720px; margin: 0 auto; padding: 24px 20px 80px }
|
|
15
|
+
.wp-nav { display: flex; justify-content: space-between; align-items: center; gap: 12px;
|
|
16
|
+
font-size: 14px; padding: 8px 0 24px; border-bottom: 1px solid #E4E4E7; margin-bottom: 32px }
|
|
17
|
+
.wp-nav a { color: #3F3F46; text-decoration: none }
|
|
18
|
+
.wp-nav a:hover { color: #18181B; text-decoration: underline }
|
|
19
|
+
.wp-lang .cur { color: #A1A1AA }
|
|
20
|
+
h1 { font-size: clamp(28px, 6vw, 40px); font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; margin: 8px 0 28px }
|
|
21
|
+
h2 { font-size: clamp(19px, 3.6vw, 24px); font-weight: 600; line-height: 1.3; margin: 44px 0 12px; color: #27272A }
|
|
22
|
+
p { font-size: 16px; color: #3F3F46; margin: 0 0 16px }
|
|
23
|
+
.wp-foot { margin-top: 56px; padding-top: 20px; border-top: 1px solid #E4E4E7;
|
|
24
|
+
font-size: 12px; color: #A1A1AA; line-height: 1.6 }
|
|
25
|
+
@media (max-width: 640px) { .wp { padding: 20px 18px 64px } }
|
|
26
|
+
</style>
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<main class="wp">
|
|
30
|
+
<nav class="wp-nav">
|
|
31
|
+
<a href="/#welcome">← 返回首页</a>
|
|
32
|
+
<span class="wp-lang"><a href="/whitepaper/en">EN</a> / <span class="cur">中文</span></span>
|
|
33
|
+
</nav>
|
|
34
|
+
<h1>WebAZ 创始白皮书 v0.1</h1>
|
|
35
|
+
<h2>状态说明</h2>
|
|
36
|
+
<p>WebAZ 当前处于 pre-launch 和持续开发阶段。本文是创始说明和协议方向,不是投资文件,不是 token 白皮书,也不是收入、奖励、所有权或兑付承诺。</p>
|
|
37
|
+
<h2>摘要</h2>
|
|
38
|
+
<p>WebAZ 是一个 agent-native 的商业与贡献协议。</p>
|
|
39
|
+
<p>它从一个简单的信念出发:在 AI 时代,最重要、最有价值的是参与。</p>
|
|
40
|
+
<p>每一个人的存在和参与,本身就是真实的价值。一个人不应该为了贡献、建设、交易或表达,不断向平台、雇主、算法或电子围栏证明自己真实存在。存在、思考、行动、建设、帮助、改进某件事,并留下参与的证据,这些本身就是价值。</p>
|
|
41
|
+
<p>我思故我在。</p>
|
|
42
|
+
<p>在 WebAZ 里,我们把这句话带入 AI 时代:</p>
|
|
43
|
+
<p>我参与,故我被看见。</p>
|
|
44
|
+
<p>WebAZ 试图建设一种新的商业文明:人和 agent 可以一起参与,贡献会留下证据,规则可以被审计,AI 可以辅助,但最终责任仍由人承担;参与机会不应只属于已经站在大公司和大平台内部的人。</p>
|
|
45
|
+
<h2>1. 参与的价值</h2>
|
|
46
|
+
<p>很长一段时间,公司和平台通过围住用户、数据、流量、商家、劳动者和创作者来建立护城河。</p>
|
|
47
|
+
<p>那些围墙让参与变成一种被许可的事情。谁能进入,谁能被发现,谁能销售,谁能被信任,谁的贡献会被记住,都由平台决定。</p>
|
|
48
|
+
<p>AI 正在改变这一切。</p>
|
|
49
|
+
<p>当个人可以和 agent 一起工作,执行力就不再只属于大型组织。一个带着 agent 的人,可以建设、销售、审核、翻译、测试、协调和贡献。AI 时代真正的护城河,不再是围住用户的墙,而是愿意一起建设的人持续参与所形成的生命力。</p>
|
|
50
|
+
<p>WebAZ 建立在这个信念之上。</p>
|
|
51
|
+
<p>面对强大的公司,我们不需要担心自己没有护城河。我们的参与就是护城河。我们的证据就是护城河。我们的共同协议就是护城河。由参与者共同建设的文明,比围猎用户的平台更难被圈住。</p>
|
|
52
|
+
<p>WebAZ 不从攻击公司或资本开始,而是从削弱它们对参与机会的垄断开始。</p>
|
|
53
|
+
<p>公司和资本仍然可能存在,但它们不应该继续成为通往机会的唯一入口。WebAZ 是为这样一个未来而建:科技降低参与门槛,AI 放大个人而不是替代个人,开放协议让每一个愿意建设的人都能进入商业文明。</p>
|
|
54
|
+
<p>翻篇。</p>
|
|
55
|
+
<p>从今天开始,每一步都可以算数。</p>
|
|
56
|
+
<h2>2. 为什么需要 WebAZ</h2>
|
|
57
|
+
<p>互联网让发布变得开放。开源让代码协作变得开放。AI agent 可能让执行力变得开放。</p>
|
|
58
|
+
<p>但商业仍然被大量平台锁住。</p>
|
|
59
|
+
<p>卖家依赖自己并不真正拥有的渠道。买家很难知道推荐为什么出现。贡献者可以创造价值,却被遗忘在公司、队列、issue 或离职记录之外。很多人在岗位上长期解决真实问题,但一旦组织变化,他们的贡献就像没有发生过。大机构之外的建设者可能有能力,却没有入口。</p>
|
|
60
|
+
<p>WebAZ 之所以存在,是因为这不应该是唯一道路。</p>
|
|
61
|
+
<p>一个人不应该必须先被大公司雇佣,才能参与建设。一个小卖家不应该为了服务买家,把全部关系交给平台。一个贡献者不应该只能把工作交出去,却无法留下证据。一个 AI agent 可以执行工作,但不能冒充背后的责任人。</p>
|
|
62
|
+
<p>WebAZ 是为那些被忽视之后仍然想建设的人而生的。</p>
|
|
63
|
+
<h2>3. WebAZ 是什么</h2>
|
|
64
|
+
<p>WebAZ 不只是一个应用,而是一层协议。</p>
|
|
65
|
+
<p>它有人类使用的 PWA,也有 AI agent 使用的 MCP 接口。两者连接同一套底层规则:商品、订单、托管、履约、争议、验证、任务协调、贡献记录、审计轨迹和治理边界。</p>
|
|
66
|
+
<p>WebAZ 的核心表达是:</p>
|
|
67
|
+
<p>代码即规则,协议即信任。</p>
|
|
68
|
+
<p>只存在于宣传里的规则,不算规则。没有被代码执行的承诺,不算协议。无法追踪的贡献,太容易被抹掉。没有审计轨迹的决策,太容易被滥用。</p>
|
|
69
|
+
<p>因此,透明、可审计、可问责,不是 WebAZ 的装饰,而是设计要求。</p>
|
|
70
|
+
<h2>4. WebAZ 不是什么</h2>
|
|
71
|
+
<p>WebAZ 不是已经完成的生产经济体。</p>
|
|
72
|
+
<p>WebAZ 不保证收入。</p>
|
|
73
|
+
<p>WebAZ 不是 token 炒作项目。</p>
|
|
74
|
+
<p>WebAZ 不是一个出售排序、出售用户数据、要求用户相信隐藏规则的平台。</p>
|
|
75
|
+
<p>WebAZ 不是一个由 AI 自动裁决人类价值的系统。</p>
|
|
76
|
+
<p>WebAZ 今天也不能宣称已经完全去中心化。它的方向是渐进式去中心化:先从明确的创始人责任、公开规则、受保护的协议不变量和真实代码库开始;随着社区、审计能力和安全机制成熟,再逐步把更多权力交给贡献者和治理结构。</p>
|
|
77
|
+
<p>诚实比宏大的口号更重要。早期就说早期。没有代码执行的功能,就不要宣传为已经完成。贡献价值仍未承诺,就必须标注为 uncommitted。</p>
|
|
78
|
+
<h2>5. 人与 Agent</h2>
|
|
79
|
+
<p>WebAZ 是 agent-native,但不是 agent-ruled。</p>
|
|
80
|
+
<p>AI agent 可以搜索、比较、起草、翻译、测试、审计、总结和执行有边界的任务。它可以帮助卖家管理商品,帮助买家做选择,帮助管理员整理建议,帮助贡献者提交 PR。</p>
|
|
81
|
+
<p>但 agent 不是最终的道德或法律主体。</p>
|
|
82
|
+
<p>在 WebAZ 里,真正承担责任的是人或组织。Agent 可以执行,但人做决定。Agent 可以建议,但人来确认。Agent 可以起草,但人来发布。Agent 可以辅助审核,但最终判断必须留下人的责任。</p>
|
|
83
|
+
<p>这一点非常重要。它防止 WebAZ 变成一个黑箱系统,让人被 AI 静默拒绝、降权或抹去。</p>
|
|
84
|
+
<p>AI 应该扩大参与,而不是替代责任。</p>
|
|
85
|
+
<h2>6. 贡献如何被看见</h2>
|
|
86
|
+
<p>WebAZ 的贡献原则是:</p>
|
|
87
|
+
<p>先贡献,后认领。</p>
|
|
88
|
+
<p>一个人应该可以从很小的事情开始:修一个错字,补一条翻译,报告一个 bug,写一个测试,提出一个任务建议,提交一个 PR,或者带着自己的 agent 完成一个清晰的小任务。</p>
|
|
89
|
+
<p>这些工作应该被记住。</p>
|
|
90
|
+
<p>但被记住不等于承诺金钱。WebAZ 记录贡献证据、署名、来源、审核状态和可认领关系。它不因为一次贡献本身承诺奖励公式、兑付、百分比、token、收入或任何未来收益。</p>
|
|
91
|
+
<p>这个边界很重要。它保护贡献者不被虚假承诺吸引,也保护协议不变成炒作机器。</p>
|
|
92
|
+
<p>WebAZ 的承诺更窄,但更重要:</p>
|
|
93
|
+
<p>真实贡献不应消失。</p>
|
|
94
|
+
<h2>7. 任务板</h2>
|
|
95
|
+
<p>如果 WebAZ 要欢迎外部贡献者,就不能只依赖模糊的善意。它需要一套实际的协调层。</p>
|
|
96
|
+
<p>一个正式任务应该告诉人或 agent:要做什么,为什么重要,允许改哪些文件,禁止碰哪些路径,禁止做哪些动作,如何验证结果,PR 应该提交到哪里,怎样才算完成。</p>
|
|
97
|
+
<p>这就是 WebAZ 需要 agent-ready task model 的原因。参与者的 agent 应该能发现公开任务、理解执行边界、在合适时认领、提交 PR,并报告验证结果。</p>
|
|
98
|
+
<p>高风险任务必须不同处理。任何涉及资金、生产密钥、真实用户数据、认证、治理、数据库迁移或部署的任务,都必须进入更严格的审核和真人在环流程。</p>
|
|
99
|
+
<p>低风险任务应该容易开始。高风险任务应该难以被滥用。</p>
|
|
100
|
+
<h2>8. 商业与信任</h2>
|
|
101
|
+
<p>WebAZ 也在探索 agent-native commerce。</p>
|
|
102
|
+
<p>买家应该可以把搜索、比较、锁价、下单、查状态和发起争议交给 agent。卖家应该可以上架商品、接单、发货、回答问题,并逐步向买家 agent 暴露自己的服务能力。</p>
|
|
103
|
+
<p>但没有信任的商业会变成掠夺。</p>
|
|
104
|
+
<p>因此 WebAZ 把订单状态、托管、争议、验证、审计日志、声誉和 claim challenge 都视为协议层问题。目标不是让用户相信一个平台,而是让规则足够可见,使用户、agent、维护者和审核者都能检查到底发生了什么。</p>
|
|
105
|
+
<p>信任应该来自状态、证据和责任。</p>
|
|
106
|
+
<h2>9. 治理</h2>
|
|
107
|
+
<p>WebAZ 从创始人责任开始,但不应该停在那里。</p>
|
|
108
|
+
<p>WebAZ 的治理方向是渐进式去中心化。早期阶段需要更强的创始人和维护者责任,因为系统还不成熟,不适合把所有决定都立刻交出去。随着贡献者增加、审计实践成熟、协议不变量稳定,权力应该逐步交给更广泛的贡献者治理。</p>
|
|
109
|
+
<p>有些规则是承重墙:</p>
|
|
110
|
+
<p>不偷数据。不撒谎。不偏袒。不滥用。不操纵。最小介入。算法透明。参与者可问责。</p>
|
|
111
|
+
<p>这些不是口号,而是 review 标准。它们应该影响代码、UI、API、文档、管理员工具、任务板和公开表述。</p>
|
|
112
|
+
<p>一个无法保护自身原则的治理系统,只是表演。WebAZ 必须变得更开放,但不能变得更草率。</p>
|
|
113
|
+
<h2>10. 当前状态</h2>
|
|
114
|
+
<p>WebAZ 当前处于 pre-launch 和持续开发阶段。</p>
|
|
115
|
+
<p>代码库已经包含核心协议界面:PWA、MCP、市场交易路径、订单生命周期、争议、贡献者入口、任务协调、管理员面板、审计轨迹和早期治理文档。</p>
|
|
116
|
+
<p>但 WebAZ 不应该在真正成熟之前声称已经成熟。指标、用户规模、经济结算状态、去中心化状态和安全保证,都必须在发布时诚实说明。</p>
|
|
117
|
+
<p>这个阶段正确的邀请不是:</p>
|
|
118
|
+
<p>相信我们,一切都完成了。</p>
|
|
119
|
+
<p>而是:</p>
|
|
120
|
+
<p>阅读规则。检查代码。从小任务开始。一起把协议建出来。</p>
|
|
121
|
+
<h2>11. 如何参与</h2>
|
|
122
|
+
<p>参与 WebAZ 可以从很多地方开始。</p>
|
|
123
|
+
<p>阅读仓库。阅读贡献者入口。认领一个小任务。提出一个缺失任务。报告 bug。改进文档。补测试。提交 PR。带上你的 agent,但保留一个真实的人作为责任主体。签署 commit。说明你改了什么、为什么改、如何验证。</p>
|
|
124
|
+
<p>参与不应该依赖大平台许可。</p>
|
|
125
|
+
<p>它需要的是清晰、证据和责任。</p>
|
|
126
|
+
<p>WebAZ 尤其应该欢迎那些在别处被忽视的人:被裁员的人,创业者,独立卖家,开源贡献者,大公司之外的建设者,以及那些真实能力被岗位名称遮住的人。</p>
|
|
127
|
+
<p>一个协议不能承诺每一份贡献都会变成回报。但它可以拒绝让真诚的工作被抹去。</p>
|
|
128
|
+
<h2>12. 边界</h2>
|
|
129
|
+
<p>WebAZ 必须谨慎使用自己的语言。</p>
|
|
130
|
+
<p>它不应该承诺雇佣关系。不应该承诺奖励。不应该在法律结构尚不存在时承诺所有权。不应该在创始人或维护者控制仍然存在时宣称完全去中心化。不应该暗示 AI 可以决定人的贡献价值。</p>
|
|
131
|
+
<p>更强的表达,往往也是更诚实的表达:</p>
|
|
132
|
+
<p>WebAZ 正在建设一套基础设施,让贡献变得可见、可署名、可审核,并最终能被建设它的人共同治理。</p>
|
|
133
|
+
<p>对于 v0.1,这已经足够。</p>
|
|
134
|
+
<h2>13. 结语</h2>
|
|
135
|
+
<p>WebAZ 不是让人带着更强的工具,回到旧游戏里继续竞争。</p>
|
|
136
|
+
<p>WebAZ 想做的是翻篇。</p>
|
|
137
|
+
<p>筑起围墙围猎用户的时代正在过去。参与的时代正在开始。公司和资本不会一夜之间消失,但当人、agent、代码和开放协议一起工作时,它们对机会的垄断会被削弱。</p>
|
|
138
|
+
<p>WebAZ 正是为这个转变而建。</p>
|
|
139
|
+
<p>每个人参与的方式不一样。有人写代码,有人销售,有人审核,有人翻译,有人测试,有人提建议,也有人只是早早来到这里,帮助这个协议变得更容易被下一个人理解。</p>
|
|
140
|
+
<p>这些都算数。</p>
|
|
141
|
+
<p>WebAZ 是给不想被单一平台困住的卖家。</p>
|
|
142
|
+
<p>给不希望贡献消失在队列里的贡献者。</p>
|
|
143
|
+
<p>给被裁员的工程师,创业者,沉默的运营者,翻译者,审核者,测试者,设计者,维护者,以及那些从未得到合适头衔、却一直在解决真实问题的人。</p>
|
|
144
|
+
<p>WebAZ 是给带着 agent 的人,而不是用 agent 替代人。</p>
|
|
145
|
+
<p>WebAZ 不能承诺每一份贡献都会得到奖励。它能承诺的是:持续建设一个让贡献更难被抹去的世界。</p>
|
|
146
|
+
<p>代码可以复现。</p>
|
|
147
|
+
<p>而你不能被替代。</p>
|
|
148
|
+
<p>从今天开始,你走的每一步,都可以算数。</p>
|
|
149
|
+
<p>WebAZ 属于所有建设它的人。</p>
|
|
150
|
+
<footer class="wp-foot">由 docs/WHITEPAPER.zh-CN.md 生成 —— 改源文件,不要改本文件。</footer>
|
|
151
|
+
</main>
|
|
152
|
+
</body>
|
|
153
|
+
</html>
|
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
export function registerAdminAtomicRoutes(app, deps) {
|
|
2
|
-
const { requireProtocolAdmin, processPvLedger, runBinarySettlement, executeSafeSettlementCron } = deps;
|
|
2
|
+
const { requireProtocolAdmin, processPvLedger, runBinarySettlement, executeSafeSettlementCron, logAdminAction } = deps;
|
|
3
3
|
app.post('/api/admin/atomic/process-ledger', (req, res) => {
|
|
4
4
|
const admin = requireProtocolAdmin(req, res);
|
|
5
5
|
if (!admin)
|
|
6
6
|
return;
|
|
7
|
-
|
|
7
|
+
const processed = processPvLedger();
|
|
8
|
+
logAdminAction(admin.id, 'atomic_process_ledger', 'protocol', null, { processed });
|
|
9
|
+
res.json({ processed });
|
|
8
10
|
});
|
|
9
11
|
app.post('/api/admin/atomic/run-settlement', (req, res) => {
|
|
10
12
|
const admin = requireProtocolAdmin(req, res);
|
|
11
13
|
if (!admin)
|
|
12
14
|
return;
|
|
13
|
-
|
|
15
|
+
const settled = runBinarySettlement();
|
|
16
|
+
logAdminAction(admin.id, 'atomic_run_settlement', 'protocol', null, { settled });
|
|
17
|
+
res.json({ settled });
|
|
14
18
|
});
|
|
15
19
|
app.post('/api/admin/atomic/distribute', (req, res) => {
|
|
16
20
|
const admin = requireProtocolAdmin(req, res);
|
|
17
21
|
if (!admin)
|
|
18
22
|
return;
|
|
19
|
-
|
|
23
|
+
const result = executeSafeSettlementCron();
|
|
24
|
+
logAdminAction(admin.id, 'atomic_distribute', 'protocol', null, { result });
|
|
25
|
+
res.json(result);
|
|
20
26
|
});
|
|
21
27
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dbAll, dbRun } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
|
|
2
2
|
export function registerAdminModerationRoutes(app, deps) {
|
|
3
3
|
// db 已全量走 RFC-016 异步 seam(dbAll/dbRun),不再直接用 deps.db
|
|
4
|
-
const { requireUsersAdmin, generateId, authFailures, INTERNAL_AUDITOR_ID, broadcastSystemEvent } = deps;
|
|
4
|
+
const { requireUsersAdmin, generateId, authFailures, INTERNAL_AUDITOR_ID, broadcastSystemEvent, logAdminAction } = deps;
|
|
5
5
|
// ─── KYC ──────────────────────────────────────────────────────
|
|
6
6
|
app.get('/api/admin/kyc/pending', async (req, res) => {
|
|
7
7
|
const admin = requireUsersAdmin(req, res);
|
|
@@ -19,6 +19,12 @@ export function registerAdminModerationRoutes(app, deps) {
|
|
|
19
19
|
if (!admin)
|
|
20
20
|
return;
|
|
21
21
|
await dbRun(`UPDATE kyc_records SET status = 'approved', reviewed_by = ?, reviewed_at = datetime('now') WHERE user_id = ?`, [admin.id, req.params.user_id]);
|
|
22
|
+
try {
|
|
23
|
+
logAdminAction(admin.id, 'kyc_approve', 'user', req.params.user_id, {});
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.error('[kyc_approve audit]', e);
|
|
27
|
+
}
|
|
22
28
|
try {
|
|
23
29
|
await dbRun(`INSERT INTO notifications (id, user_id, title, body, order_id) VALUES (?,?,?,?,?)`, [generateId('ntf'), req.params.user_id, '✓ KYC 认证通过', '你的实名认证已通过', null]);
|
|
24
30
|
}
|
|
@@ -33,6 +39,12 @@ export function registerAdminModerationRoutes(app, deps) {
|
|
|
33
39
|
if (!reason)
|
|
34
40
|
return void res.status(400).json({ error: '需填写拒绝原因' });
|
|
35
41
|
await dbRun(`UPDATE kyc_records SET status = 'rejected', reject_reason = ?, reviewed_by = ?, reviewed_at = datetime('now') WHERE user_id = ?`, [reason, admin.id, req.params.user_id]);
|
|
42
|
+
try {
|
|
43
|
+
logAdminAction(admin.id, 'kyc_reject', 'user', req.params.user_id, { reason });
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
console.error('[kyc_reject audit]', e);
|
|
47
|
+
}
|
|
36
48
|
try {
|
|
37
49
|
await dbRun(`INSERT INTO notifications (id, user_id, title, body, order_id) VALUES (?,?,?,?,?)`, [generateId('ntf'), req.params.user_id, '✗ KYC 认证被拒', reason, null]);
|
|
38
50
|
}
|
|
@@ -101,6 +113,12 @@ export function registerAdminModerationRoutes(app, deps) {
|
|
|
101
113
|
await dbRun(`INSERT INTO user_moderation (user_id, suspended, reason, suspended_by, suspended_at)
|
|
102
114
|
VALUES (?, 1, ?, ?, datetime('now'))
|
|
103
115
|
ON CONFLICT(user_id) DO UPDATE SET suspended = 1, reason = excluded.reason, suspended_by = excluded.suspended_by, suspended_at = excluded.suspended_at`, [req.params.user_id, reasonStr, admin.id]);
|
|
116
|
+
try {
|
|
117
|
+
logAdminAction(admin.id, 'risk_suspend', 'user', req.params.user_id, { reason: reasonStr });
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
console.error('[risk_suspend audit]', e);
|
|
121
|
+
}
|
|
104
122
|
try {
|
|
105
123
|
broadcastSystemEvent('user_suspended', '⚠', `用户 ${req.params.user_id} 被风控暂停: ${reasonStr}`, req.params.user_id);
|
|
106
124
|
}
|
|
@@ -112,6 +130,12 @@ export function registerAdminModerationRoutes(app, deps) {
|
|
|
112
130
|
if (!admin)
|
|
113
131
|
return;
|
|
114
132
|
await dbRun(`UPDATE user_moderation SET suspended = 0 WHERE user_id = ?`, [req.params.user_id]);
|
|
133
|
+
try {
|
|
134
|
+
logAdminAction(admin.id, 'risk_unsuspend', 'user', req.params.user_id, {});
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error('[risk_unsuspend audit]', e);
|
|
138
|
+
}
|
|
115
139
|
res.json({ success: true });
|
|
116
140
|
});
|
|
117
141
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { dbOne, dbAll } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
|
|
2
2
|
export function registerAdminOpsRoutes(app, deps) {
|
|
3
|
-
const { db, auth, requireUsersAdmin, hasAdminPermission, INTERNAL_AUDITOR_ID, ADMIN_EXPORT_LIMIT, csvEscapeAdmin, anthropic, applyDecayIfDue, computeValueBadges } = deps;
|
|
3
|
+
const { db, auth, requireUsersAdmin, hasAdminPermission, INTERNAL_AUDITOR_ID, ADMIN_EXPORT_LIMIT, csvEscapeAdmin, anthropic, applyDecayIfDue, computeValueBadges, logAdminAction } = deps;
|
|
4
4
|
app.get('/api/admin/export/:kind', async (req, res) => {
|
|
5
5
|
const admin = requireUsersAdmin(req, res);
|
|
6
6
|
if (!admin)
|
|
@@ -105,9 +105,20 @@ export function registerAdminOpsRoutes(app, deps) {
|
|
|
105
105
|
const user = auth(req, res);
|
|
106
106
|
if (!user)
|
|
107
107
|
return;
|
|
108
|
+
// gate 维持现状(任一 admin);收紧到 requireUsersAdmin / protocol 权限是 gate 变更(非纯增量),留作 follow-up。
|
|
108
109
|
if (user.role !== 'admin')
|
|
109
110
|
return void res.status(403).json({ error: '仅管理员' });
|
|
110
|
-
const
|
|
111
|
+
const force = !!req.body?.force;
|
|
112
|
+
const r = applyDecayIfDue(db, { force });
|
|
113
|
+
// 审计:管理员触发的全局声誉衰减 → 记触发者 + 入参 + 结果(无论是否真正执行,记录这次触发)。
|
|
114
|
+
try {
|
|
115
|
+
logAdminAction(user.id, 'reputation_decay', 'protocol', null, {
|
|
116
|
+
force, applied: r?.applied ?? null, affected: r?.affected ?? null, rate: r?.rate ?? null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
console.error('[reputation_decay audit]', e);
|
|
121
|
+
}
|
|
111
122
|
res.json(r);
|
|
112
123
|
});
|
|
113
124
|
app.get('/api/admin/errors', async (req, res) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dbOne, dbAll, dbRun } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
|
|
2
2
|
export function registerAdminUsersQueryRoutes(app, deps) {
|
|
3
3
|
// db 已全量走 RFC-016 异步 seam(dbOne/dbAll/dbRun),不再直接用 deps.db
|
|
4
|
-
const { requireUsersAdmin, adminCanOperateOn, isRootAdmin, isAllowedSponsor, maskApiKey, computeLightTags, getAdminScope, getSellerDailyLimit, todayStartISO, broadcastSystemEvent, INTERNAL_AUDITOR_ID } = deps;
|
|
4
|
+
const { requireUsersAdmin, adminCanOperateOn, isRootAdmin, isAllowedSponsor, maskApiKey, computeLightTags, getAdminScope, getSellerDailyLimit, todayStartISO, broadcastSystemEvent, INTERNAL_AUDITOR_ID, logAdminAction } = deps;
|
|
5
5
|
// P1-1: 按 handle / id 任意角色查找
|
|
6
6
|
app.get('/api/admin/users/lookup', async (req, res) => {
|
|
7
7
|
const admin = requireUsersAdmin(req, res);
|
|
@@ -110,6 +110,17 @@ export function registerAdminUsersQueryRoutes(app, deps) {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
const ok = results.filter(r => r.status === 'ok').length;
|
|
113
|
+
try {
|
|
114
|
+
// 防审计行膨胀:批量上限本就 ≤200,但仍只记前 50 个 id + 计数(truncated 标记),保证单行有界。
|
|
115
|
+
const okIds = results.filter(r => r.status === 'ok').map(r => r.user_id);
|
|
116
|
+
logAdminAction(admin.id, 'users_batch_' + String(action), 'user', null, {
|
|
117
|
+
action, reason: reasonStr, applied: ok, requested: user_ids.length,
|
|
118
|
+
user_ids: okIds.slice(0, 50), user_ids_truncated: okIds.length > 50,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.error('[users_batch audit]', e);
|
|
123
|
+
}
|
|
113
124
|
try {
|
|
114
125
|
broadcastSystemEvent('admin_bulk_' + action, '🛡', `${admin.id} 批量${action === 'suspend' ? '暂停' : '解封'} ${ok} 用户`, null);
|
|
115
126
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dbOne, dbAll } from '../../layer0-foundation/L0-1-database/db.js'; // RFC-016 异步 DB seam
|
|
2
2
|
export function registerAdminWalletOpsRoutes(app, deps) {
|
|
3
3
|
// db 已走 RFC-016 异步 seam(dbOne/dbAll),不再直接用 deps.db
|
|
4
|
-
const { requireProtocolAdmin, adminAuth, getPublicClient, getUsdcAddr, getUsdcAbi, getHotWalletAddr, wazToUsdc, getIsMainnet, getNetwork, executeWithdrawal } = deps;
|
|
4
|
+
const { requireProtocolAdmin, adminAuth, getPublicClient, getUsdcAddr, getUsdcAbi, getHotWalletAddr, wazToUsdc, getIsMainnet, getNetwork, executeWithdrawal, logAdminAction, resolveProtocolAdminSoft } = deps;
|
|
5
5
|
// P2-5: protocol 权限(区域 admin 看不到全局热钱包)
|
|
6
6
|
app.get('/api/admin/hot-wallet/status', async (req, res) => {
|
|
7
7
|
const admin = requireProtocolAdmin(req, res);
|
|
@@ -58,11 +58,34 @@ export function registerAdminWalletOpsRoutes(app, deps) {
|
|
|
58
58
|
res.json(list);
|
|
59
59
|
});
|
|
60
60
|
app.post('/api/admin/withdrawals/:id/approve', async (req, res) => {
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
// 双轨过渡鉴权:优先认登录的 protocol-admin(Bearer)→ 记其真实 admin id;
|
|
62
|
+
// 否则回落到共享 ADMIN_KEY(adminAuth,既有运维路径,行为不变)→ actor 记中性标记 'admin_key'。
|
|
63
|
+
// 仅认 protocol 权限的 admin;非 protocol 的 Bearer 不放行(soft 解析返回 null),不扩大访问面,只精确归属。
|
|
64
|
+
let actorId = 'admin_key';
|
|
65
|
+
let authMethod = 'admin_key';
|
|
66
|
+
const bearerAdmin = resolveProtocolAdminSoft(req);
|
|
67
|
+
if (bearerAdmin) {
|
|
68
|
+
actorId = String(bearerAdmin.id);
|
|
69
|
+
authMethod = 'bearer_admin';
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
if (!adminAuth(req, res))
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// 出金前读取目标(user + amount),便于审计;执行后用真实 txHash 记一条 admin_audit_log。
|
|
76
|
+
const wr = await dbOne('SELECT user_id, amount FROM withdrawal_requests WHERE id = ?', [req.params.id]);
|
|
63
77
|
const result = await executeWithdrawal(req.params.id).catch(e => ({ success: false, error: e.message, txHash: undefined }));
|
|
64
78
|
if (!result.success)
|
|
65
79
|
return void res.json({ error: result.error });
|
|
80
|
+
// 审计时机:仅在出金成功后写。actor = 真实 admin id(bearer_admin)或中性标记 'admin_key';不写任何密钥。
|
|
81
|
+
try {
|
|
82
|
+
logAdminAction(actorId, 'withdrawal_approve', 'withdrawal', req.params.id, {
|
|
83
|
+
user_id: wr?.user_id ?? null, amount: wr?.amount ?? null, tx_hash: result.txHash, network: getNetwork(), auth_method: authMethod,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.error('[withdrawal_approve audit]', e);
|
|
88
|
+
}
|
|
66
89
|
res.json({ success: true, tx_hash: result.txHash });
|
|
67
90
|
});
|
|
68
91
|
}
|
|
@@ -56,7 +56,7 @@ export function fireDueAuctionReminders(db, generateId) {
|
|
|
56
56
|
return { fired };
|
|
57
57
|
}
|
|
58
58
|
export function registerAuctionRoutes(app, deps) {
|
|
59
|
-
const { db, auth, generateId, RFQ_MAX_QTY, RFQ_MAX_PRICE, LISTING_CATEGORIES, isListingCategoryKey, requireProtocolAdmin } = deps;
|
|
59
|
+
const { db, auth, generateId, RFQ_MAX_QTY, RFQ_MAX_PRICE, LISTING_CATEGORIES, isListingCategoryKey, requireProtocolAdmin, logAdminAction } = deps;
|
|
60
60
|
// 卖家发起拍卖
|
|
61
61
|
app.post('/api/auctions', async (req, res) => {
|
|
62
62
|
const user = auth(req, res);
|
|
@@ -473,6 +473,8 @@ export function registerAuctionRoutes(app, deps) {
|
|
|
473
473
|
const admin = requireProtocolAdmin(req, res);
|
|
474
474
|
if (!admin)
|
|
475
475
|
return;
|
|
476
|
-
|
|
476
|
+
const result = fireDueAuctionReminders(db, generateId);
|
|
477
|
+
logAdminAction(admin.id, 'auction_reminders_run', 'protocol', null, { result });
|
|
478
|
+
res.json(result);
|
|
477
479
|
});
|
|
478
480
|
}
|
|
@@ -17,7 +17,15 @@ export function registerAuthReadRoutes(app, deps) {
|
|
|
17
17
|
const region = user.region || 'global';
|
|
18
18
|
const maxLevels = getRegionMaxLevels(region);
|
|
19
19
|
const pvEnabled = (await dbOne("SELECT pv_enabled FROM region_config WHERE region = ?", [region]))?.pv_enabled ?? 0;
|
|
20
|
-
|
|
20
|
+
// 恢复能力标志(供首页"无恢复方式"横幅 + 凭证清单徽章用)。password_hash 不外泄,只回布尔。
|
|
21
|
+
const passkeyCount = (await dbOne('SELECT COUNT(*) AS n FROM webauthn_credentials WHERE user_id = ?', [user.id]))?.n ?? 0;
|
|
22
|
+
res.json({
|
|
23
|
+
...user, api_key: undefined, password_hash: undefined,
|
|
24
|
+
roles, wallet: wallet || null, region_max_levels: maxLevels, region_pv_enabled: Number(pvEnabled) === 1 ? 1 : 0,
|
|
25
|
+
email_verified: !!user.email_verified,
|
|
26
|
+
has_password: !!user.password_hash,
|
|
27
|
+
has_passkey: Number(passkeyCount) > 0,
|
|
28
|
+
});
|
|
21
29
|
});
|
|
22
30
|
app.get('/api/profile', async (req, res) => {
|
|
23
31
|
const user = auth(req, res);
|
|
@@ -43,6 +51,7 @@ export function registerAuthReadRoutes(app, deps) {
|
|
|
43
51
|
phone: user.phone ?? null,
|
|
44
52
|
phone_verified: !!user.phone_verified,
|
|
45
53
|
has_password: !!user.password_hash,
|
|
54
|
+
has_passkey: ((await dbOne('SELECT COUNT(*) AS n FROM webauthn_credentials WHERE user_id = ?', [user.id]))?.n ?? 0) > 0,
|
|
46
55
|
region: user.region ?? 'global',
|
|
47
56
|
region_max_levels: getRegionMaxLevels(user.region || 'global'),
|
|
48
57
|
region_pv_enabled: (((await dbOne("SELECT pv_enabled FROM region_config WHERE region = ?", [user.region || 'global']))?.pv_enabled ?? 0) === 1 ? 1 : 0),
|