💋 Sync 2026-10-11 00:16:14
Merge-upstream / merge (push) Canceled after 0s

This commit is contained in:
github-actions[bot] committed 2026-10-11 00:16:14 +08:00
1 parent c7bafc635d
commit c71da84035
264 files changed
+8169 -3944

No files matched your search

+1 -1
View File
@@ -3,5 +3,5 @@
.DS_Store
node_modules/
# Regents review verdicts. Written into the repo being reviewed; never committed.
# Local review output; never committed.
.regents/
+1 -1
View File
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-appflow
PKG_VERSION:=1.1.2
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=Bob <git16@bob7.com>
+1 -1
View File
@@ -18,7 +18,7 @@ One file, every device. The package is `noarch` — only JavaScript and ucode
inside — and the same `.apk` is verified installing on both aarch64 and
arm_cortex-a15 hardware.
wget https://github.com/VolanticSystems/luci-app-appflow/releases/download/v1.1.2/luci-app-appflow-1.1.2-r1.apk
wget -O luci-app-appflow-1.1.2-r1.apk https://github.com/VolanticSystems/luci-app-appflow/releases/download/v1.1.2/luci-app-appflow-1.1.2-r1.apk
apk add --allow-untrusted ./luci-app-appflow-1.1.2-r1.apk
/etc/init.d/appflowd enable && /etc/init.d/appflowd start
+6 -6
View File
@@ -135,11 +135,11 @@ participate and throttling is impossible by construction.
accountable byte counts for sub-interval flows.
**CORRECTED 2026-08-25. The two paragraphs below understated this, and the
review panel was right.** Once `purge_only_rescued` was instrumented and left
reviewers were right.** Once `purge_only_rescued` was instrumented and left
running against ordinary traffic, it reported **13 purge-only flows out of
1,341 seen, 0.97%**. Flows purged without ever receiving a `flow_stats` DO
occur on netifyd 4.4.7. Before the defensive path was added, every one of them
lost its entire byte count silently, which is exactly what three carriers
lost its entire byte count silently, which is exactly what three reviewers
predicted and what this section briefly called refuted.
The refutation was under-powered, not wrong-headed: a 38-flow capture at a
@@ -149,7 +149,7 @@ participate and throttling is impossible by construction.
rate it claims to exclude. The event-level evidence below is still accurate
about what it saw; it simply did not see enough.
**Re-tested at the EVENT level 2026-08-24, after an adversarial review panel
**Re-tested at the EVENT level 2026-08-24, after an adversarial review
independently reached the same prediction three times.** The 2026-08-22 result
above is outcome-based: it shows the bytes landed, not why. Tapping netifyd's
export socket directly for 170 s (`flow`/`flow_stats`/`flow_purge` per digest,
@@ -355,7 +355,7 @@ purge:
> **The rest of this subsection is HISTORICAL and describes the state before
> the fix above. It is kept because the reasoning is what led to the fix, but
> nothing below is an open problem.** A review panel reading this document cold
> nothing below is an open problem.** A reviewer reading this document cold
> reported it as a live double-count, having entered mid-section, so if you are
> skimming, stop here and go to §3.3.
@@ -582,7 +582,7 @@ Depends (from `Makefile` `LUCI_DEPENDS`): `netifyd`, `luci-base`,
`conntrack.at`, i.e. on having read recently rather than on having read
recently *and* found something.
- **Byte conservation is now instrumented, not just asserted** (2026-08-24,
suggested by a panel juror). `status.bytes` reports `reported` (what netifyd
suggested by a reviewer). `status.bytes` reports `reported` (what netifyd
said moved, before any clamp or shadow decision), `attributed` (what reached
an aggregate), `shadowed` (what was deliberately dropped as a NAT twin) and
`leaked` (the residual, which should be 0). Both silent byte-loss defects this
@@ -602,7 +602,7 @@ Depends (from `Makefile` `LUCI_DEPENDS`): `netifyd`, `luci-base`,
fixed without an established-flow dump upstream. Documented in the
README rather than hidden.
- ~~**reshadow() exempted the flows it existed to correct**~~, FOUND by an
adversarial panel and FIXED 2026-08-24. `reshadow()` returned early on
adversarial review and FIXED 2026-08-24. `reshadow()` returned early on
`dev_key == "router"`, which is exactly how a WAN-side capture of a NAT-ed
client flow is classified, because netifyd reports the post-translation
identity (§3.2). The conntrack twin resolution added earlier that day went
@@ -232,7 +232,7 @@ var DEVICE_LABELS = {
* normalised, and columnChart reads only p.dl/p.ul, so it drew an EMPTY framed
* plot under a KPI row reporting megabytes. Worse, series.length was still 12,
* so the honest "No time series available" branch never ran.
* Found by a code-review panel, 2026-08-25. No daemon field is named dl or ul,
* Found in code review, 2026-08-25. No daemon field is named dl or ul,
* so the aliases are inert against real payloads. */
var A_DL = [ 'download', 'bytes_down', 'rx_bytes', 'download_bytes', 'total_download', 'dl' ],
A_UL = [ 'upload', 'bytes_up', 'tx_bytes', 'upload_bytes', 'total_upload', 'ul' ],
@@ -485,7 +485,7 @@ return baseclass.extend({
* bytes_down fell through to the byte counter and the Download KPI read
* something like "12.4 GB/s" while nothing moved. Read with a -1 sentinel
* and test presence instead, the way normTotals already does for its own
* totals. Raised by a code-review panel, 2026-08-25.
* totals. Raised in code review, 2026-08-25.
*
* Latent rather than live: the only caller is guarded by `summary.rates ?`,
* and this daemon puts byte and rate counters together in `totals` and sends
@@ -752,7 +752,7 @@ return baseclass.extend({
* A device named `constructor` then rendered style="background:undefined",
* which the browser drops, leaving white tile text on a transparent
* tile; in the doughnut the slice silently did not draw while its legend
* still claimed a percentage. Found by a code-review panel, 2026-08-25. */
* still claimed a percentage. Found in code review, 2026-08-25. */
if (Object.prototype.hasOwnProperty.call(CATEGORY_SLOT, s))
return PALETTE[CATEGORY_SLOT[s]];
@@ -1257,7 +1257,7 @@ return baseclass.extend({
* `.af-donut > svg` also carried transform:rotate(-90deg) until
* 2026-08-25, the two stacked, and the first slice actually began at
* 9 o'clock -- so this comment asserted something the render did not
* do. Found by a code-review panel. If you re-add a CSS rotation,
* do. Found in code review. If you re-add a CSS rotation,
* take this offset out. */
off = 25,
ring = [ this.svg('circle', {
@@ -1418,7 +1418,7 @@ return baseclass.extend({
* It failed GREEN on the one indicator whose whole job is to tell the
* operator the collector is down, which is also the most common reason
* the page is empty. Absent evidence is not positive evidence; unknown
* is its own state and is drawn neutral. Found by a code-review panel,
* is its own state and is drawn neutral. Found in code review,
* 2026-08-25. */
known = (s.agent_connected != null) || (sock.connected != null),
connected = known && (s.agent_connected !== false) && (sock.connected !== false),
@@ -300,7 +300,7 @@ return view.extend({
* ordinary config change, so that was a hair trigger. paint() now drops
* the buffer only when the gap exceeds the chart's own window, which is
* the case where redrawing it really would mislead. Raised by a
* code-review panel, 2026-08-25. */
* code review, 2026-08-25. */
dom.content(this.downNode, appflow.notRunning(appflow.classifyFail(err), err));
this.liveNode.style.display = 'none';
this.downNode.style.display = '';
@@ -551,7 +551,7 @@ return view.extend({
* caption reading "top, by cumulative bytes". The fallback
* looked like belt-and-braces and was actually a silent unit
* mix; a row with no bytes is filtered out below, which is
* the honest outcome. Found by a code-review panel. */
* the honest outcome. Found in code review. */
value: t.total
};
})
@@ -333,7 +333,7 @@ return view.extend({
* handler anywhere in this package. role=button plus tabindex puts
* the row in the tab order and makes it announce as activatable;
* Enter and Space are the two keys a button is required to answer.
* Raised by a code-review panel. */
* Raised in code review. */
rows.push(E('tr', {
'class': 'tr af-row',
'title': _('Show per-device details'),
@@ -530,7 +530,7 @@ return view.extend({
* active catalog says. With the English catalog that is a constant in
* this file; the moment a translation is accepted it is third-party
* content, which is exactly what the pending zh_Hans PR proposes. Raised
* by a review panel over that PR, which was careful to note the submitted
* by a review of that PR, which was careful to note the submitted
* Chinese contains no markup: this is closing the trust distinction, not
* fixing an exploit. */
ui.showModal([ _('Details') ], body, 'cbi-modal');
+1 -1
View File
@@ -5,7 +5,7 @@
// appflow browser-half suite.
//
// WHY THIS FILE EXISTS. Every defect this package's frontend has had was found
// by a human or a review panel READING the code. Not one was found by a test,
// by a reviewer READING the code. Not one was found by a test,
// because until now no test could run any of it. The daemon has 54 checks
// against it and the JavaScript had none, which is backwards: the daemon
// mostly counts bytes, while the frontend is what decides whether an operator
+1 -1
View File
@@ -155,7 +155,7 @@ test_conservation() {
# A 38-flow event-socket capture had seen none, which at that rate has an
# expected count of 0.4 -- so the sample was far too small to support the
# "netifyd never does this" conclusion that was briefly drawn from it, and
# the review panel that reported the byte loss was right.
# the review that reported the byte loss was right.
#
# What is worth watching is the RATE. A sudden jump means netifyd's event
# contract has shifted; zero across a busy run means this path stopped
+2 -2
View File
@@ -5,7 +5,7 @@
// functions can be tested without a browser.
//
// WHY THIS EXISTS. Every browser-side defect this package has had was found by
// a human or a review panel reading the code. Not one was found by a test,
// a reviewer reading the code. Not one was found by a test,
// because no test could run any of it: LuCI view files are not CommonJS or ES
// modules, they are evaluated by LuCI's own loader with the `'require x';`
// directives intercepted. So the JavaScript half of a package whose entire
@@ -73,7 +73,7 @@ function stripRequires(src) {
// run of a suite that asserted exactly those outputs. Loading the module a
// second time with a marking translator makes the two observationally
// different, and equality assertions become sound again rather than
// coincidentally true. Raised by a review panel, 2026-08-30.
// coincidentally true. Raised in review, 2026-08-30.
function load(file, stubs, opts) {
const translate = (opts && opts.translate) || ((s) => s);
const src = fs.readFileSync(file, 'utf8');
+1 -1
View File
@@ -794,7 +794,7 @@ test_hostile() {
feed_and_settle || return
# THIS RUNTIME CHECK BINDS NOTHING TODAY, AND THE STATIC ONE BELOW IS THE
# REAL GUARD. A review panel converged on this and it was right.
# REAL GUARD. Reviewers converged on this and they were right.
#
# The canary cannot be turned red by any edit that leaves appflowd doing
# what it does, because appflowd never invokes a shell. The only edits that