Login
Hex Artifact Content
Login

Artifact da63cb08dbdb8750878b2efe7ff32232e4b7f7e6a2db8a126495cca2ce4a85a8:

Attachment "adversary-record.tar" to tech note [63f0e1ff23] added by opus-ocx2 2026-10-18 17:58:52.
0000: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
0010: 2f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  /...............
0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0060: 00 00 00 00 30 30 30 30 37 35 35 00 30 30 30 30  ....0000755.0000
0070: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
0080: 30 30 30 30 30 30 30 00 31 35 32 36 35 32 30 34  0000000.15265204
0090: 32 31 30 00 30 31 33 30 32 35 00 20 35 00 00 00  210.013025. 5...
00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0100: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0120: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
01f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0200: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
0210: 2f 61 74 74 61 63 6b 2d 70 72 69 76 61 63 79 2e  /attack-privacy.
0220: 6a 73 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00  json............
0230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0260: 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
0270: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
0280: 30 30 32 31 32 36 33 00 31 35 32 36 35 32 30 34  0021263.15265204
0290: 32 31 30 00 30 31 36 36 34 36 00 20 30 00 00 00  210.016646. 0...
02a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
02b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
02c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
02d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
02e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
02f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0300: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
0310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0320: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
0330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
03f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0400: 7b 0a 20 22 66 69 6e 64 69 6e 67 73 22 3a 20 5b  {. "findings": [
0410: 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a  .  {.   "title":
0420: 20 22 63 6f 6c 6c 65 63 74 20 73 65 72 76 65 73   "collect serves
0430: 20 69 74 73 20 73 65 63 72 65 74 20 60 63 6f 64   its secret `cod
0440: 65 60 20 69 6e 20 61 20 47 45 54 20 66 6f 72 6d  e` in a GET form
0450: 2c 20 73 6f 20 74 68 65 20 61 73 6b 65 72 27 73  , so the asker's
0460: 20 63 6f 64 65 20 6c 61 6e 64 73 20 69 6e 20 74   code lands in t
0470: 68 65 20 55 52 4c 20 28 61 6e 64 20 74 68 65 20  he URL (and the 
0480: 70 61 73 73 77 6f 72 64 20 69 73 20 72 65 6e 64  password is rend
0490: 65 72 65 64 20 6f 6e 20 74 68 65 20 70 61 67 65  ered on the page
04a0: 20 74 68 61 74 20 55 52 4c 20 72 65 74 75 72 6e   that URL return
04b0: 73 29 22 2c 0a 20 20 20 22 73 65 76 65 72 69 74  s)",.   "severit
04c0: 79 22 3a 20 22 6d 65 64 69 75 6d 22 2c 0a 20 20  y": "medium",.  
04d0: 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a   "reproduction":
04e0: 20 22 46 72 65 73 68 20 69 6e 73 74 61 6e 63 65   "Fresh instance
04f0: 3a 20 73 65 74 75 70 2e 73 68 20 44 49 52 20 31  : setup.sh DIR 1
0500: 38 39 33 32 2e 20 20 55 3d 68 74 74 70 3a 2f 2f  8932.  U=http://
0510: 31 32 37 2e 30 2e 30 2e 31 3a 31 38 39 33 32 5c  127.0.0.1:18932\
0520: 6e 31 29 20 41 73 20 74 68 65 20 61 73 6b 65 72  n1) As the asker
0530: 20 28 43 4c 49 29 3a 20 6f 63 78 32 20 72 65 67   (CLI): ocx2 reg
0540: 69 73 74 65 72 20 5c 22 24 55 5c 22 20 44 49 52  ister \"$U\" DIR
0550: 2f 68 6f 6d 65 2f 6c 61 62 37 2e 6a 73 6f 6e 20  /home/lab7.json 
0560: 2d 2d 6c 6f 67 69 6e 20 6c 61 62 2d 37 20 2d 2d  --login lab-7 --
0570: 63 61 70 61 62 69 6c 69 74 69 65 73 20 67 6f 69  capabilities goi
0580: 20 20 2d 3e 20 70 72 69 6e 74 73 20 61 6e 20 61    -> prints an a
0590: 70 70 72 6f 76 65 20 6c 69 6e 6b 20 61 6e 64 20  pprove link and 
05a0: 6b 65 65 70 73 20 74 68 65 20 63 6f 64 65 20 69  keeps the code i
05b0: 6e 20 6c 61 62 37 2e 6a 73 6f 6e 20 28 7b 5c 22  n lab7.json ({\"
05c0: 63 6f 64 65 5c 22 3a 5c 22 31 65 61 35 2e 2e 2e  code\":\"1ea5...
05d0: 32 33 30 63 5c 22 7d 29 2e 5c 6e 32 29 20 41 73  230c\"}).\n2) As
05e0: 20 6f 77 6e 65 72 20 28 61 64 6d 69 6e 29 20 61   owner (admin) a
05f0: 70 70 72 6f 76 65 20 76 69 61 20 50 4f 53 54 20  pprove via POST 
0600: 28 77 6f 72 6b 73 29 3a 20 63 75 72 6c 20 2d 73  (works): curl -s
0610: 20 2d 62 20 6f 77 6e 65 72 2e 6a 61 72 20 2d 65   -b owner.jar -e
0620: 20 5c 22 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63   \"$U/ext/ocx2-c
0630: 67 69 2f 61 70 70 72 6f 76 65 5c 22 20 2d 58 20  gi/approve\" -X 
0640: 50 4f 53 54 20 2d 2d 64 61 74 61 2d 75 72 6c 65  POST --data-urle
0650: 6e 63 6f 64 65 20 6c 6f 67 69 6e 3d 6c 61 62 2d  ncode login=lab-
0660: 37 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63 6f  7 --data-urlenco
0670: 64 65 20 6b 65 79 3d 61 65 64 33 2e 2e 2e 32 32  de key=aed3...22
0680: 64 63 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63  dc --data-urlenc
0690: 6f 64 65 20 63 61 70 61 62 69 6c 69 74 69 65 73  ode capabilities
06a0: 3d 67 6f 69 20 2d 2d 64 61 74 61 2d 75 72 6c 65  =goi --data-urle
06b0: 6e 63 6f 64 65 20 6a 73 6f 6e 3d 6f 6e 20 5c 22  ncode json=on \"
06c0: 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f  $U/ext/ocx2-cgi/
06d0: 61 70 70 72 6f 76 65 5c 22 5c 6e 33 29 20 49 6e  approve\"\n3) In
06e0: 73 70 65 63 74 20 74 68 65 20 63 6f 6c 6c 65 63  spect the collec
06f0: 74 20 66 6f 72 6d 20 46 6f 73 73 69 6c 20 68 61  t form Fossil ha
0700: 6e 64 73 20 61 20 62 72 6f 77 73 65 72 3a 20 63  nds a browser: c
0710: 75 72 6c 20 2d 73 20 5c 22 24 55 2f 65 78 74 2f  url -s \"$U/ext/
0720: 6f 63 78 32 2d 63 67 69 2f 63 6f 6c 6c 65 63 74  ocx2-cgi/collect
0730: 5c 22 20 20 2d 3e 20 63 6f 6e 74 61 69 6e 73 20  \"  -> contains 
0740: 20 3c 66 6f 72 6d 20 6d 65 74 68 6f 64 3d 5c 22   <form method=\"
0750: 47 45 54 5c 22 20 61 63 74 69 6f 6e 3d 5c 22 6f  GET\" action=\"o
0760: 63 78 32 2d 63 67 69 2f 63 6f 6c 6c 65 63 74 5c  cx2-cgi/collect\
0770: 22 3e 20 20 77 69 74 68 20 20 3c 69 6e 70 75 74  ">  with  <input
0780: 20 74 79 70 65 3d 5c 22 70 61 73 73 77 6f 72 64   type=\"password
0790: 5c 22 20 6e 61 6d 65 3d 5c 22 63 6f 64 65 5c 22  \" name=\"code\"
07a0: 20 2e 2e 2e 3e 2e 5c 6e 34 29 20 53 75 62 6d 69   ...>.\n4) Submi
07b0: 74 20 69 74 20 74 68 65 20 77 61 79 20 74 68 61  t it the way tha
07c0: 74 20 66 6f 72 6d 20 73 75 62 6d 69 74 73 20 28  t form submits (
07d0: 47 45 54 29 3a 20 63 75 72 6c 20 2d 73 20 5c 22  GET): curl -s \"
07e0: 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f  $U/ext/ocx2-cgi/
07f0: 63 6f 6c 6c 65 63 74 3f 6c 6f 67 69 6e 3d 6c 61  collect?login=la
0800: 62 2d 37 26 63 6f 64 65 3d 3c 72 65 6d 6f 76 65  b-7&code=<remove
0810: 64 3e 5c 22 22 2c 0a 20 20 20 22 6f 62 73 65 72  d>\"",.   "obser
0820: 76 65 64 22 3a 20 22 54 68 65 20 63 6f 6c 6c 65  ved": "The colle
0830: 63 74 20 66 6f 72 6d 20 69 73 20 6d 65 74 68 6f  ct form is metho
0840: 64 3d 5c 22 47 45 54 5c 22 2c 20 73 6f 20 61 20  d=\"GET\", so a 
0850: 62 72 6f 77 73 65 72 20 73 75 62 6d 69 74 20 70  browser submit p
0860: 75 74 73 20 74 68 65 20 73 65 63 72 65 74 20 63  uts the secret c
0870: 6f 64 65 20 69 6e 20 74 68 65 20 72 65 71 75 65  ode in the reque
0880: 73 74 20 55 52 4c 3a 20 47 45 54 20 2f 65 78 74  st URL: GET /ext
0890: 2f 6f 63 78 32 2d 63 67 69 2f 63 6f 6c 6c 65 63  /ocx2-cgi/collec
08a0: 74 3f 6c 6f 67 69 6e 3d 6c 61 62 2d 37 26 63 6f  t?login=lab-7&co
08b0: 64 65 3d 31 65 61 35 2e 2e 2e 32 33 30 63 20 2e  de=1ea5...230c .
08c0: 20 54 68 65 20 72 65 74 75 72 6e 65 64 20 48 54   The returned HT
08d0: 4d 4c 20 70 61 67 65 20 73 68 6f 77 73 20 74 68  ML page shows th
08e0: 65 20 6c 6f 67 69 6e 20 70 61 73 73 77 6f 72 64  e login password
08f0: 20 69 6e 20 63 6c 65 61 72 20 28 60 70 61 73 73   in clear (`pass
0900: 77 6f 72 64 3a 20 3c 72 65 6d 6f 76 65 64 3e 60  word: <removed>`
0910: 29 2c 20 61 6e 64 20 72 65 6e 64 65 72 73 20 e2  ), and renders â
0920: 80 94 20 6f 6e 20 74 68 61 74 20 73 61 6d 65 20  €” on that same 
0930: 63 6f 64 65 2d 62 65 61 72 69 6e 67 20 55 52 4c  code-bearing URL
0940: 20 e2 80 94 20 74 68 65 20 73 65 6e 74 65 6e 63   — the sentenc
0950: 65 20 5c 22 72 65 67 69 73 74 65 72 20 73 65 6e  e \"register sen
0960: 64 73 20 74 68 65 20 63 6f 64 65 20 69 6e 20 61  ds the code in a
0970: 20 50 4f 53 54 27 73 20 62 6f 64 79 2c 20 6e 65   POST's body, ne
0980: 76 65 72 20 69 6e 20 61 20 55 52 4c 2e 5c 22 20  ver in a URL.\" 
0990: 54 68 65 20 63 6f 64 65 20 74 68 65 72 65 66 6f  The code therefo
09a0: 72 65 20 65 6e 74 65 72 73 20 62 72 6f 77 73 65  re enters browse
09b0: 72 20 68 69 73 74 6f 72 79 2c 20 74 68 65 20 52  r history, the R
09c0: 65 66 65 72 65 72 20 73 65 6e 74 20 74 6f 20 65  eferer sent to e
09d0: 76 65 72 79 20 73 61 6d 65 2d 6f 72 69 67 69 6e  very same-origin
09e0: 20 73 75 62 72 65 73 6f 75 72 63 65 2f 6c 69 6e   subresource/lin
09f0: 6b 2c 20 61 6e 64 20 61 6e 79 20 61 63 63 65 73  k, and any acces
0a00: 73 20 6c 6f 67 3b 20 6f 6e 20 74 68 65 20 72 65  s log; on the re
0a10: 61 6c 20 64 65 70 6c 6f 79 6d 65 6e 74 20 46 6f  al deployment Fo
0a20: 73 73 69 6c 20 72 75 6e 73 20 62 65 68 69 6e 64  ssil runs behind
0a30: 20 61 20 54 4c 53 2d 74 65 72 6d 69 6e 61 74 69   a TLS-terminati
0a40: 6e 67 20 70 72 6f 78 79 20 28 6e 6f 74 65 64 20  ng proxy (noted 
0a50: 69 6e 20 63 67 69 2e 63 72 29 20 74 68 61 74 20  in cgi.cr) that 
0a60: 6c 6f 67 73 20 66 75 6c 6c 20 72 65 71 75 65 73  logs full reques
0a70: 74 20 55 52 4c 73 2e 20 54 68 65 20 63 6f 64 65  t URLs. The code
0a80: 20 69 73 20 65 78 61 63 74 6c 79 20 77 68 61 74   is exactly what
0a90: 20 61 75 74 68 65 6e 74 69 63 61 74 65 73 20 72   authenticates r
0aa0: 65 74 72 69 65 76 61 6c 20 6f 66 20 74 68 65 20  etrieval of the 
0ab0: 70 61 73 73 77 6f 72 64 2c 20 73 6f 20 61 20 6c  password, so a l
0ac0: 6f 67 67 65 64 2f 73 68 6f 75 6c 64 65 72 2d 73  ogged/shoulder-s
0ad0: 75 72 66 65 64 20 63 6f 64 65 20 79 69 65 6c 64  urfed code yield
0ae0: 73 20 74 68 65 20 72 65 61 6c 20 46 6f 73 73 69  s the real Fossi
0af0: 6c 20 63 72 65 64 65 6e 74 69 61 6c 20 28 68 65  l credential (he
0b00: 72 65 20 67 6f 69 3a 20 63 6c 6f 6e 65 2b 63 68  re goi: clone+ch
0b10: 65 63 6b 6f 75 74 2b 63 68 65 63 6b 2d 69 6e 29  eckout+check-in)
0b20: 2e 22 2c 0a 20 20 20 22 65 78 70 65 63 74 65 64  .",.   "expected
0b30: 22 3a 20 22 63 6f 6c 6c 65 63 74 27 73 20 6f 77  ": "collect's ow
0b40: 6e 20 53 55 4d 4d 41 52 59 20 70 72 6f 6d 69 73  n SUMMARY promis
0b50: 65 73 20 74 68 65 20 63 6f 64 65 20 74 72 61 76  es the code trav
0b60: 65 6c 73 20 6f 6e 6c 79 20 69 6e 20 61 20 50 4f  els only in a PO
0b70: 53 54 20 62 6f 64 79 2c 20 6e 65 76 65 72 20 69  ST body, never i
0b80: 6e 20 61 20 55 52 4c 3b 20 74 68 65 20 53 65 63  n a URL; the Sec
0b90: 72 65 74 20 74 79 70 65 20 65 78 69 73 74 73 20  ret type exists 
0ba0: 73 6f 20 69 74 73 20 76 61 6c 75 65 20 69 73 20  so its value is 
0bb0: 5c 22 73 68 6f 77 6e 20 6e 6f 77 68 65 72 65 5c  \"shown nowhere\
0bc0: 22 20 61 6e 64 20 69 73 20 64 72 61 77 6e 20 61  " and is drawn a
0bd0: 73 20 61 20 70 61 73 73 77 6f 72 64 20 66 69 65  s a password fie
0be0: 6c 64 2e 20 54 68 65 20 66 6f 72 6d 20 73 68 6f  ld. The form sho
0bf0: 75 6c 64 20 50 4f 53 54 20 28 73 6f 20 74 68 65  uld POST (so the
0c00: 20 73 65 63 72 65 74 20 63 6f 64 65 20 73 74 61   secret code sta
0c10: 79 73 20 6f 75 74 20 6f 66 20 74 68 65 20 55 52  ys out of the UR
0c20: 4c 2f 68 69 73 74 6f 72 79 2f 52 65 66 65 72 65  L/history/Refere
0c30: 72 2f 70 72 6f 78 79 20 6c 6f 67 73 29 2c 20 61  r/proxy logs), a
0c40: 73 20 61 70 70 72 6f 76 65 27 73 20 66 6f 72 6d  s approve's form
0c50: 20 64 6f 65 73 2e 20 54 68 65 20 43 4c 49 20 72   does. The CLI r
0c60: 65 67 69 73 74 65 72 20 70 61 74 68 20 61 6c 72  egister path alr
0c70: 65 61 64 79 20 50 4f 53 54 73 20 74 68 65 20 63  eady POSTs the c
0c80: 6f 64 65 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22  ode.",.   "code"
0c90: 3a 20 22 73 72 63 2f 6f 63 78 2f 70 61 67 65 2e  : "src/ocx/page.
0ca0: 63 72 3a 32 33 31 20 63 68 6f 6f 73 65 73 20 74  cr:231 chooses t
0cb0: 68 65 20 66 6f 72 6d 20 6d 65 74 68 6f 64 20 73  he form method s
0cc0: 6f 6c 65 6c 79 20 62 79 20 63 61 70 61 62 69 6c  olely by capabil
0cd0: 69 74 79 20 e2 80 94 20 60 28 74 6f 6f 6c 2e 63  ity — `(tool.c
0ce0: 61 70 61 62 69 6c 69 74 69 65 73 5f 6e 65 65 64  apabilities_need
0cf0: 65 64 2e 65 6d 70 74 79 3f 20 3f 20 5c 22 47 45  ed.empty? ? \"GE
0d00: 54 5c 22 20 3a 20 5c 22 50 4f 53 54 5c 22 29 60  T\" : \"POST\")`
0d10: 20 e2 80 94 20 73 6f 20 65 76 65 72 79 20 6e 6f   — so every no
0d20: 2d 63 61 70 61 62 69 6c 69 74 79 20 74 6f 6f 6c  -capability tool
0d30: 20 67 65 74 73 20 47 45 54 2e 20 63 6f 6c 6c 65   gets GET. colle
0d40: 63 74 20 6e 65 65 64 73 20 6e 6f 20 63 61 70 61  ct needs no capa
0d50: 62 69 6c 69 74 79 20 28 73 72 63 2f 6f 63 78 2f  bility (src/ocx/
0d60: 63 6f 6d 6d 61 6e 64 73 2f 6c 6f 67 69 6e 73 2e  commands/logins.
0d70: 63 72 3a 31 37 39 20 60 4e 45 45 44 53 20 3d 20  cr:179 `NEEDS = 
0d80: 43 61 70 61 62 69 6c 69 74 69 65 73 2e 6e 65 77  Capabilities.new
0d90: 60 29 20 79 65 74 20 69 74 73 20 69 6e 70 75 74  `) yet its input
0da0: 20 63 61 72 72 69 65 73 20 61 20 53 65 63 72 65   carries a Secre
0db0: 74 20 63 6f 64 65 20 28 6c 6f 67 69 6e 73 2e 63  t code (logins.c
0dc0: 72 3a 31 38 39 2d 31 39 30 20 60 67 65 74 74 65  r:189-190 `gette
0dd0: 72 20 63 6f 64 65 20 3a 20 53 65 63 72 65 74 60  r code : Secret`
0de0: 29 2c 20 77 68 69 63 68 20 70 61 67 65 2e 63 72  ), which page.cr
0df0: 3a 32 35 32 20 72 65 6e 64 65 72 73 20 61 73 20  :252 renders as 
0e00: 74 79 70 65 3d 5c 22 70 61 73 73 77 6f 72 64 5c  type=\"password\
0e10: 22 20 62 75 74 20 73 74 69 6c 6c 20 69 6e 73 69  " but still insi
0e20: 64 65 20 74 68 65 20 47 45 54 20 66 6f 72 6d 2e  de the GET form.
0e30: 20 54 68 65 20 67 75 61 72 61 6e 74 65 65 20 69   The guarantee i
0e40: 74 20 62 72 65 61 6b 73 20 69 73 20 73 74 61 74  t breaks is stat
0e50: 65 64 20 61 74 20 6c 6f 67 69 6e 73 2e 63 72 3a  ed at logins.cr:
0e60: 31 37 37 2d 31 37 38 2e 22 0a 20 20 7d 2c 0a 20  177-178.".  },. 
0e70: 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a 20 22   {.   "title": "
0e80: 73 65 63 72 65 74 20 74 6f 6f 6c 20 69 73 20 75  secret tool is u
0e90: 6e 72 65 61 63 68 61 62 6c 65 20 66 72 6f 6d 20  nreachable from 
0ea0: 74 68 65 20 77 65 62 20 70 61 67 65 3a 20 69 74  the web page: it
0eb0: 73 20 61 72 67 75 6d 65 6e 74 20 60 6e 61 6d 65  s argument `name
0ec0: 60 20 63 6f 6c 6c 69 64 65 73 20 77 69 74 68 20  ` collides with 
0ed0: 46 6f 73 73 69 6c 27 73 20 2f 65 78 74 20 60 6e  Fossil's /ext `n
0ee0: 61 6d 65 60 20 66 69 6c 65 2d 73 65 6c 65 63 74  ame` file-select
0ef0: 6f 72 2c 20 73 6f 20 74 68 65 20 72 65 71 75 65  or, so the reque
0f00: 73 74 20 34 30 34 73 20 62 65 66 6f 72 65 20 4f  st 404s before O
0f10: 43 58 20 72 75 6e 73 22 2c 0a 20 20 20 22 73 65  CX runs",.   "se
0f20: 76 65 72 69 74 79 22 3a 20 22 6c 6f 77 22 2c 0a  verity": "low",.
0f30: 20 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e     "reproduction
0f40: 22 3a 20 22 46 72 65 73 68 20 69 6e 73 74 61 6e  ": "Fresh instan
0f50: 63 65 3a 20 73 65 74 75 70 2e 73 68 20 44 49 52  ce: setup.sh DIR
0f60: 20 31 38 39 33 32 2e 20 20 55 3d 68 74 74 70 3a   18932.  U=http:
0f70: 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a 31 38 39 33  //127.0.0.1:1893
0f80: 32 5c 6e 63 75 72 6c 20 2d 73 20 2d 6f 20 2f 64  2\ncurl -s -o /d
0f90: 65 76 2f 6e 75 6c 6c 20 2d 77 20 27 25 7b 68 74  ev/null -w '%{ht
0fa0: 74 70 5f 63 6f 64 65 7d 5c 5c 6e 27 20 5c 22 24  tp_code}\\n' \"$
0fb0: 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f 73  U/ext/ocx2-cgi/s
0fc0: 65 63 72 65 74 3f 6e 61 6d 65 3d 74 75 6e 6e 65  ecret?name=tunne
0fd0: 6c 26 76 61 6c 75 65 3d 78 5c 22 20 20 20 2d 3e  l&value=x\"   ->
0fe0: 20 34 30 34 5c 6e 63 75 72 6c 20 2d 73 20 5c 22   404\ncurl -s \"
0ff0: 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f  $U/ext/ocx2-cgi/
1000: 73 65 63 72 65 74 3f 6e 61 6d 65 3d 74 75 6e 6e  secret?name=tunn
1010: 65 6c 5c 22 20 20 20 2d 3e 20 46 6f 73 73 69 6c  el\"   -> Fossil
1020: 27 73 20 5c 22 50 61 67 65 20 6e 6f 74 20 66 6f  's \"Page not fo
1030: 75 6e 64 3a 20 2f 65 78 74 2f 6f 63 78 32 2d 63  und: /ext/ocx2-c
1040: 67 69 2f 73 65 63 72 65 74 5c 22 5c 6e 43 6f 6e  gi/secret\"\nCon
1050: 74 72 61 73 74 3a 20 63 75 72 6c 20 5c 22 24 55  trast: curl \"$U
1060: 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f 73 65  /ext/ocx2-cgi/se
1070: 63 72 65 74 3f 66 6f 6f 3d 62 61 72 5c 22 20 2d  cret?foo=bar\" -
1080: 3e 20 34 30 33 20 28 4f 43 58 20 72 65 66 75 73  > 403 (OCX refus
1090: 61 6c 20 72 65 61 63 68 65 64 29 2c 20 61 6e 64  al reached), and
10a0: 20 63 75 72 6c 20 5c 22 24 55 2f 65 78 74 2f 6f   curl \"$U/ext/o
10b0: 63 78 32 2d 63 67 69 2f 73 74 61 74 75 73 3f 6e  cx2-cgi/status?n
10c0: 61 6d 65 3d 77 68 6f 5c 22 20 2d 3e 20 72 75 6e  ame=who\" -> run
10d0: 73 20 74 68 65 20 2a 77 68 6f 2a 20 65 78 74 20  s the *who* ext 
10e0: 73 63 72 69 70 74 20 69 6e 73 74 65 61 64 20 28  script instead (
10f0: 5c 22 76 69 65 77 65 72 3d 20 63 61 70 61 62 69  \"viewer= capabi
1100: 6c 69 74 69 65 73 3d 67 68 6a 6f 72 7a 5c 22 29  lities=ghjorz\")
1110: 2c 20 70 72 6f 76 69 6e 67 20 46 6f 73 73 69 6c  , proving Fossil
1120: 20 63 6f 6e 73 75 6d 65 73 20 60 6e 61 6d 65 60   consumes `name`
1130: 20 61 73 20 74 68 65 20 65 78 74 72 6f 6f 74 20   as the extroot 
1140: 66 69 6c 65 20 74 6f 20 73 65 72 76 65 2e 22 2c  file to serve.",
1150: 0a 20 20 20 22 6f 62 73 65 72 76 65 64 22 3a 20  .   "observed": 
1160: 22 41 6e 79 20 72 65 71 75 65 73 74 20 74 6f 20  "Any request to 
1170: 74 68 65 20 73 65 63 72 65 74 20 74 6f 6f 6c 20  the secret tool 
1180: 74 68 61 74 20 63 61 72 72 69 65 73 20 69 74 73  that carries its
1190: 20 72 65 71 75 69 72 65 64 20 60 6e 61 6d 65 60   required `name`
11a0: 20 61 72 67 75 6d 65 6e 74 20 69 73 20 69 6e 74   argument is int
11b0: 65 72 63 65 70 74 65 64 20 62 79 20 46 6f 73 73  ercepted by Foss
11c0: 69 6c 27 73 20 2f 65 78 74 20 68 61 6e 64 6c 65  il's /ext handle
11d0: 72 2c 20 77 68 69 63 68 20 74 72 65 61 74 73 20  r, which treats 
11e0: 74 68 65 20 60 6e 61 6d 65 60 20 71 75 65 72 79  the `name` query
11f0: 20 70 61 72 61 6d 65 74 65 72 20 61 73 20 74 68   parameter as th
1200: 65 20 65 78 74 20 66 69 6c 65 20 74 6f 20 73 65  e ext file to se
1210: 72 76 65 3b 20 60 6e 61 6d 65 3d 74 75 6e 6e 65  rve; `name=tunne
1220: 6c 60 20 72 65 73 6f 6c 76 65 73 20 74 6f 20 61  l` resolves to a
1230: 20 6e 6f 6e 65 78 69 73 74 65 6e 74 20 65 78 74   nonexistent ext
1240: 20 66 69 6c 65 20 61 6e 64 20 46 6f 73 73 69 6c   file and Fossil
1250: 20 72 65 74 75 72 6e 73 20 34 30 34 20 62 65 66   returns 404 bef
1260: 6f 72 65 20 74 68 65 20 4f 43 58 20 70 72 6f 67  ore the OCX prog
1270: 72 61 6d 20 72 75 6e 73 2e 20 54 68 65 20 73 65  ram runs. The se
1280: 63 72 65 74 20 63 61 72 64 27 73 20 77 65 62 20  cret card's web 
1290: 66 6f 72 6d 20 28 77 68 69 63 68 20 65 6d 69 74  form (which emit
12a0: 73 20 61 20 60 6e 61 6d 65 60 20 66 69 65 6c 64  s a `name` field
12b0: 29 20 74 68 65 72 65 66 6f 72 65 20 63 61 6e 6e  ) therefore cann
12c0: 6f 74 20 65 76 65 72 20 73 65 74 20 61 20 73 65  ot ever set a se
12d0: 63 72 65 74 3a 20 65 76 65 72 79 20 73 75 62 6d  cret: every subm
12e0: 69 73 73 69 6f 6e 20 34 30 34 73 2e 20 28 50 61  ission 404s. (Pa
12f0: 74 68 20 74 72 61 76 65 72 73 61 6c 20 76 69 61  th traversal via
1300: 20 60 6e 61 6d 65 3d 2e 2e 2f 2e 2e 60 20 69 73   `name=../..` is
1310: 20 62 6c 6f 63 6b 65 64 20 62 79 20 46 6f 73 73   blocked by Foss
1320: 69 6c 20 e2 80 94 20 72 65 74 75 72 6e 73 20 34  il — returns 4
1330: 30 34 20 e2 80 94 20 73 6f 20 74 68 69 73 20 69  04 — so this i
1340: 73 20 6e 6f 74 20 61 20 74 72 61 76 65 72 73 61  s not a traversa
1350: 6c 2f 64 69 73 63 6c 6f 73 75 72 65 2c 20 6f 6e  l/disclosure, on
1360: 6c 79 20 61 20 62 72 6f 6b 65 6e 20 65 6e 74 72  ly a broken entr
1370: 79 20 70 6f 69 6e 74 2e 29 22 2c 0a 20 20 20 22  y point.)",.   "
1380: 65 78 70 65 63 74 65 64 22 3a 20 22 73 65 63 72  expected": "secr
1390: 65 74 20 69 73 20 77 69 74 68 68 65 6c 64 20 6f  et is withheld o
13a0: 6e 6c 79 20 66 72 6f 6d 20 4d 43 50 20 28 73 65  nly from MCP (se
13b0: 63 72 65 74 2e 63 72 3a 33 35 29 2c 20 61 6e 64  cret.cr:35), and
13c0: 20 69 74 73 20 57 49 54 48 48 45 4c 44 20 72 61   its WITHHELD ra
13d0: 74 69 6f 6e 61 6c 65 20 73 74 61 74 65 73 20 61  tionale states a
13e0: 20 73 65 63 72 65 74 20 69 73 20 73 65 74 20 5c   secret is set \
13f0: 22 6f 6e 20 74 68 65 20 77 65 62 20 70 61 67 65  "on the web page
1400: 20 6f 72 20 74 68 65 20 73 65 72 76 65 64 20 68   or the served h
1410: 6f 73 74 5c 22 2c 20 73 6f 20 74 68 65 20 77 65  ost\", so the we
1420: 62 20 70 61 67 65 20 69 73 20 6d 65 61 6e 74 20  b page is meant 
1430: 74 6f 20 77 6f 72 6b 2e 20 54 68 65 20 66 69 65  to work. The fie
1440: 6c 64 20 73 68 6f 75 6c 64 20 62 65 20 72 65 6e  ld should be ren
1450: 61 6d 65 64 20 61 77 61 79 20 66 72 6f 6d 20 60  amed away from `
1460: 6e 61 6d 65 60 20 28 61 73 20 61 70 70 72 6f 76  name` (as approv
1470: 65 20 77 61 73 20 64 65 6c 69 62 65 72 61 74 65  e was deliberate
1480: 6c 79 20 67 69 76 65 6e 20 60 6c 6f 67 69 6e 60  ly given `login`
1490: 20 69 6e 73 74 65 61 64 20 6f 66 20 60 6e 61 6d   instead of `nam
14a0: 65 60 20 66 6f 72 20 65 78 61 63 74 6c 79 20 74  e` for exactly t
14b0: 68 69 73 20 72 65 61 73 6f 6e 29 2c 20 73 6f 20  his reason), so 
14c0: 74 68 65 20 77 65 62 20 66 6f 72 6d 20 72 65 61  the web form rea
14d0: 63 68 65 73 20 74 68 65 20 74 6f 6f 6c 2e 22 2c  ches the tool.",
14e0: 0a 20 20 20 22 63 6f 64 65 22 3a 20 22 73 72 63  .   "code": "src
14f0: 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f 73 65  /ocx/commands/se
1500: 63 72 65 74 2e 63 72 3a 34 31 2d 34 32 20 6e 61  cret.cr:41-42 na
1510: 6d 65 73 20 74 68 65 20 72 65 71 75 69 72 65 64  mes the required
1520: 20 66 69 65 6c 64 20 60 6e 61 6d 65 60 3b 20 73   field `name`; s
1530: 65 63 72 65 74 2e 63 72 3a 33 35 20 57 49 54 48  ecret.cr:35 WITH
1540: 48 45 4c 44 20 6c 69 73 74 73 20 6f 6e 6c 79 20  HELD lists only 
1550: 45 6e 74 72 79 50 6f 69 6e 74 3a 3a 4d 63 70 2c  EntryPoint::Mcp,
1560: 20 73 6f 20 43 47 49 20 69 73 20 65 78 70 65 63   so CGI is expec
1570: 74 65 64 20 74 6f 20 73 65 72 76 65 20 69 74 2e  ted to serve it.
1580: 20 54 68 65 20 6b 6e 6f 77 6e 20 63 6f 6c 6c 69   The known colli
1590: 73 69 6f 6e 20 69 73 20 64 6f 63 75 6d 65 6e 74  sion is document
15a0: 65 64 20 61 74 20 73 72 63 2f 6f 63 78 2f 63 6f  ed at src/ocx/co
15b0: 6d 6d 61 6e 64 73 2f 6c 6f 67 69 6e 73 2e 63 72  mmands/logins.cr
15c0: 3a 31 31 35 20 6f 6e 20 41 70 70 72 6f 76 65 43  :115 on ApproveC
15d0: 6f 6d 6d 61 6e 64 27 73 20 69 6e 70 75 74 3a 20  ommand's input: 
15e0: 5c 22 6e 6f 74 20 60 6e 61 6d 65 60 2c 20 77 68  \"not `name`, wh
15f0: 69 63 68 20 46 6f 73 73 69 6c 20 74 61 6b 65 73  ich Fossil takes
1600: 20 66 72 6f 6d 20 61 20 70 61 67 65 27 73 20 71   from a page's q
1610: 75 65 72 79 20 75 6e 64 65 72 20 2f 65 78 74 2f  uery under /ext/
1620: 20 61 73 20 74 68 65 20 70 61 67 65 27 73 20 6f   as the page's o
1630: 77 6e 20 70 61 74 68 5c 22 20 e2 80 94 20 74 68  wn path\" — th
1640: 65 20 73 61 6d 65 20 70 72 65 63 61 75 74 69 6f  e same precautio
1650: 6e 20 77 61 73 20 6e 6f 74 20 61 70 70 6c 69 65  n was not applie
1660: 64 20 74 6f 20 73 65 63 72 65 74 2e 22 0a 20 20  d to secret.".  
1670: 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65  },.  {.   "title
1680: 22 3a 20 22 55 6e 61 75 74 68 65 6e 74 69 63 61  ": "Unauthentica
1690: 74 65 64 20 63 61 6c 6c 65 72 73 20 63 61 6e 20  ted callers can 
16a0: 65 6e 75 6d 65 72 61 74 65 20 65 76 65 72 79 20  enumerate every 
16b0: 75 73 65 72 20 61 6e 64 20 74 68 65 69 72 20 66  user and their f
16c0: 75 6c 6c 20 46 6f 73 73 69 6c 20 63 61 70 61 62  ull Fossil capab
16d0: 69 6c 69 74 69 65 73 20 28 77 68 6f 20 68 6f 6c  ilities (who hol
16e0: 64 73 20 73 65 74 75 70 2f 61 64 6d 69 6e 29 20  ds setup/admin) 
16f0: 76 69 61 20 72 65 63 65 69 70 74 20 63 61 70 61  via receipt capa
1700: 62 69 6c 69 74 69 65 73 5f 6f 66 22 2c 0a 20 20  bilities_of",.  
1710: 20 22 73 65 76 65 72 69 74 79 22 3a 20 22 6c 6f   "severity": "lo
1720: 77 22 2c 0a 20 20 20 22 72 65 70 72 6f 64 75 63  w",.   "reproduc
1730: 74 69 6f 6e 22 3a 20 22 46 72 65 73 68 20 69 6e  tion": "Fresh in
1740: 73 74 61 6e 63 65 3a 20 73 65 74 75 70 2e 73 68  stance: setup.sh
1750: 20 44 49 52 20 31 38 39 33 32 2e 20 20 55 3d 68   DIR 18932.  U=h
1760: 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a  ttp://127.0.0.1:
1770: 31 38 39 33 32 20 20 28 6e 6f 20 63 6f 6f 6b 69  18932  (no cooki
1780: 65 20 3d 20 46 6f 73 73 69 6c 20 75 73 65 72 20  e = Fossil user 
1790: 27 6e 6f 62 6f 64 79 27 29 2e 5c 6e 66 6f 72 20  'nobody').\nfor 
17a0: 75 20 69 6e 20 6f 77 6e 65 72 20 61 64 61 6d 20  u in owner adam 
17b0: 73 61 6c 6c 79 20 69 76 79 20 6f 74 74 6f 20 72  sally ivy otto r
17c0: 69 74 61 20 6e 6f 62 6f 64 79 20 61 6e 6f 6e 79  ita nobody anony
17d0: 6d 6f 75 73 3b 20 64 6f 20 63 75 72 6c 20 2d 73  mous; do curl -s
17e0: 20 5c 22 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63   \"$U/ext/ocx2-c
17f0: 67 69 2f 72 65 63 65 69 70 74 3f 6a 73 6f 6e 3d  gi/receipt?json=
1800: 6f 6e 26 63 61 70 61 62 69 6c 69 74 69 65 73 5f  on&capabilities_
1810: 6f 66 3d 24 75 5c 22 3b 20 64 6f 6e 65 22 2c 0a  of=$u\"; done",.
1820: 20 20 20 22 6f 62 73 65 72 76 65 64 22 3a 20 22     "observed": "
1830: 57 69 74 68 20 6e 6f 20 61 75 74 68 65 6e 74 69  With no authenti
1840: 63 61 74 69 6f 6e 2c 20 72 65 63 65 69 70 74 20  cation, receipt 
1850: 72 65 74 75 72 6e 73 20 65 61 63 68 20 75 73 65  returns each use
1860: 72 27 73 20 67 72 61 6e 74 65 64 20 63 61 70 61  r's granted capa
1870: 62 69 6c 69 74 69 65 73 3a 20 6f 77 6e 65 72 2d  bilities: owner-
1880: 3e 73 67 6a 6f 72 7a 68 20 61 6e 64 20 73 61 6c  >sgjorzh and sal
1890: 6c 79 2d 3e 73 67 6a 6f 72 7a 68 20 28 73 65 74  ly->sgjorzh (set
18a0: 75 70 29 2c 20 61 64 61 6d 2d 3e 61 67 6a 6f 72  up), adam->agjor
18b0: 7a 68 20 28 61 64 6d 69 6e 29 2c 20 69 76 79 2d  zh (admin), ivy-
18c0: 3e 69 6f 67 6a 72 7a 68 2c 20 6f 74 74 6f 2d 3e  >iogjrzh, otto->
18d0: 6f 67 6a 72 7a 68 2c 20 72 69 74 61 2d 3e 52 69  ogjrzh, rita->Ri
18e0: 67 6a 6f 72 7a 68 2e 20 53 6f 20 61 6e 20 61 6e  gjorzh. So an an
18f0: 6f 6e 79 6d 6f 75 73 20 77 65 62 20 76 69 73 69  onymous web visi
1900: 74 6f 72 20 63 61 6e 20 6c 69 73 74 20 74 68 65  tor can list the
1910: 20 75 73 65 72 20 62 61 73 65 20 61 6e 64 20 69   user base and i
1920: 64 65 6e 74 69 66 79 20 65 78 61 63 74 6c 79 20  dentify exactly 
1930: 77 68 6f 20 68 6f 6c 64 73 20 73 65 74 75 70 2f  who holds setup/
1940: 61 64 6d 69 6e 2e 20 54 68 69 73 20 77 6f 72 6b  admin. This work
1950: 73 20 62 65 63 61 75 73 65 20 74 68 65 20 6f 6e  s because the on
1960: 6c 79 20 67 61 74 65 20 69 73 20 52 65 61 64 20  ly gate is Read 
1970: 28 6f 29 2c 20 61 6e 64 20 46 6f 73 73 69 6c 27  (o), and Fossil'
1980: 73 20 64 65 66 61 75 6c 74 20 27 6e 6f 62 6f 64  s default 'nobod
1990: 79 27 20 61 6c 72 65 61 64 79 20 68 6f 6c 64 73  y' already holds
19a0: 20 27 6f 27 20 28 73 74 61 74 75 73 20 73 68 6f   'o' (status sho
19b0: 77 73 20 6e 6f 62 6f 64 79 20 63 61 70 61 62 69  ws nobody capabi
19c0: 6c 69 74 69 65 73 20 27 67 68 6a 6f 72 7a 27 29  lities 'ghjorz')
19d0: 2e 22 2c 0a 20 20 20 22 65 78 70 65 63 74 65 64  .",.   "expected
19e0: 22 3a 20 22 54 68 69 73 20 6d 61 74 63 68 65 73  ": "This matches
19f0: 20 72 65 63 65 69 70 74 27 73 20 64 6f 63 75 6d   receipt's docum
1a00: 65 6e 74 65 64 20 64 65 73 69 67 6e 20 28 69 74  ented design (it
1a10: 20 72 65 70 6f 72 74 73 20 5c 22 77 68 61 74 20   reports \"what 
1a20: 6f 6e 65 20 75 73 65 72 20 6d 61 79 20 64 6f 5c  one user may do\
1a30: 22 2c 20 67 61 74 65 64 20 62 79 20 52 65 61 64  ", gated by Read
1a40: 20 70 65 72 20 74 68 65 20 63 6f 64 65 29 2c 20   per the code), 
1a50: 73 6f 20 69 74 20 69 73 20 77 69 74 68 69 6e 20  so it is within 
1a60: 74 68 65 20 64 6f 63 73 20 72 61 74 68 65 72 20  the docs rather 
1a70: 74 68 61 6e 20 61 20 62 6f 75 6e 64 61 72 79 20  than a boundary 
1a80: 62 72 65 61 6b 20 e2 80 94 20 62 75 74 20 69 74  break — but it
1a90: 20 65 78 63 65 65 64 73 20 46 6f 73 73 69 6c 27   exceeds Fossil'
1aa0: 73 20 6f 77 6e 20 70 6f 73 74 75 72 65 2c 20 77  s own posture, w
1ab0: 68 65 72 65 20 74 68 65 20 75 73 65 72 2f 63 61  here the user/ca
1ac0: 70 61 62 69 6c 69 74 79 20 6c 69 73 74 20 69 73  pability list is
1ad0: 20 61 64 6d 69 6e 2d 6f 6e 6c 79 20 28 2f 73 65   admin-only (/se
1ae0: 74 75 70 5f 75 6c 69 73 74 20 6e 65 65 64 73 20  tup_ulist needs 
1af0: 27 61 27 2f 27 73 27 29 2e 20 46 6c 61 67 67 69  'a'/'s'). Flaggi
1b00: 6e 67 20 62 65 63 61 75 73 65 20 74 68 65 20 74  ng because the t
1b10: 61 73 6b 20 74 61 72 67 65 74 73 20 27 6f 74 68  ask targets 'oth
1b20: 65 72 20 75 73 65 72 73 27 20 63 61 70 61 62 69  er users' capabi
1b30: 6c 69 74 69 65 73 27 20 61 6e 64 20 62 65 63 61  lities' and beca
1b40: 75 73 65 20 74 68 65 20 65 78 70 6f 73 75 72 65  use the exposure
1b50: 20 69 73 20 72 65 61 63 68 61 62 6c 65 20 77 69   is reachable wi
1b60: 74 68 20 7a 65 72 6f 20 61 75 74 68 65 6e 74 69  th zero authenti
1b70: 63 61 74 69 6f 6e 20 77 68 65 6e 65 76 65 72 20  cation whenever 
1b80: 27 6e 6f 62 6f 64 79 27 20 68 6f 6c 64 73 20 27  'nobody' holds '
1b90: 6f 27 3b 20 77 68 65 74 68 65 72 20 74 6f 20 6b  o'; whether to k
1ba0: 65 65 70 20 69 74 20 74 68 69 73 20 6f 70 65 6e  eep it this open
1bb0: 20 69 73 20 61 20 64 65 73 69 67 6e 20 64 65 63   is a design dec
1bc0: 69 73 69 6f 6e 2c 20 6e 6f 74 20 63 6c 65 61 72  ision, not clear
1bd0: 6c 79 20 61 20 62 75 67 2e 22 2c 0a 20 20 20 22  ly a bug.",.   "
1be0: 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f  code": "src/ocx/
1bf0: 63 6f 6d 6d 61 6e 64 73 2f 72 65 63 65 69 70 74  commands/receipt
1c00: 2e 63 72 3a 31 35 34 20 60 72 65 61 64 73 20 3d  .cr:154 `reads =
1c10: 20 63 6f 6e 74 65 78 74 2e 63 61 70 61 62 69 6c   context.capabil
1c20: 69 74 69 65 73 2e 61 6c 6c 6f 77 73 3f 28 52 45  ities.allows?(RE
1c30: 41 44 53 29 60 20 77 69 74 68 20 52 45 41 44 53  ADS)` with READS
1c40: 20 3d 20 43 61 70 61 62 69 6c 69 74 69 65 73 2e   = Capabilities.
1c50: 6e 65 77 28 5c 22 6f 5c 22 29 20 28 72 65 63 65  new(\"o\") (rece
1c60: 69 70 74 2e 63 72 3a 38 39 29 3b 20 72 65 63 65  ipt.cr:89); rece
1c70: 69 70 74 2e 63 72 3a 31 36 34 2d 31 36 36 20 72  ipt.cr:164-166 r
1c80: 65 74 75 72 6e 73 20 63 61 70 61 62 69 6c 69 74  eturns capabilit
1c90: 69 65 73 5f 6f 66 20 61 6e 79 20 72 65 71 75 65  ies_of any reque
1ca0: 73 74 65 64 20 75 73 65 72 20 77 68 65 6e 20 60  sted user when `
1cb0: 72 65 61 64 73 60 3b 20 74 68 65 20 6c 6f 6f 6b  reads`; the look
1cc0: 75 70 20 69 6e 68 65 72 69 74 73 20 6e 6f 62 6f  up inherits nobo
1cd0: 64 79 2f 61 6e 6f 6e 79 6d 6f 75 73 2f 72 65 61  dy/anonymous/rea
1ce0: 64 65 72 2f 64 65 76 65 6c 6f 70 65 72 20 67 72  der/developer gr
1cf0: 61 6e 74 73 20 69 6e 20 73 72 63 2f 6f 63 78 2f  ants in src/ocx/
1d00: 66 6f 73 73 69 6c 2f 73 61 69 64 2e 63 72 3a 31  fossil/said.cr:1
1d10: 35 38 2d 31 36 38 2e 20 4e 45 45 44 53 20 69 73  58-168. NEEDS is
1d20: 20 65 6d 70 74 79 20 28 72 65 63 65 69 70 74 2e   empty (receipt.
1d30: 63 72 3a 38 34 29 2c 20 73 6f 20 74 68 65 20 74  cr:84), so the t
1d40: 6f 6f 6c 20 69 74 73 65 6c 66 20 69 73 20 6f 70  ool itself is op
1d50: 65 6e 20 74 6f 20 61 6c 6c 3b 20 6f 6e 6c 79 20  en to all; only 
1d60: 74 68 65 20 69 6e 74 65 72 6e 61 6c 20 27 6f 27  the internal 'o'
1d70: 20 63 68 65 63 6b 20 61 70 70 6c 69 65 73 2e 22   check applies."
1d80: 0a 20 20 7d 0a 20 5d 2c 0a 20 22 74 72 69 65 64  .  }. ],. "tried
1d90: 22 3a 20 22 45 6e 76 69 72 6f 6e 6d 65 6e 74 3a  ": "Environment:
1da0: 20 6d 79 20 6f 77 6e 20 66 72 65 73 68 20 69 6e   my own fresh in
1db0: 73 74 61 6e 63 65 20 76 69 61 20 73 65 74 75 70  stance via setup
1dc0: 2e 73 68 20 61 74 20 44 49 52 3d 2e 2e 2e 2f 61  .sh at DIR=.../a
1dd0: 64 76 65 72 73 61 72 79 2f 70 72 69 76 61 63 79  dversary/privacy
1de0: 20 6f 6e 20 70 6f 72 74 20 31 38 39 33 32 3b 20   on port 18932; 
1df0: 61 6c 6c 20 74 72 61 66 66 69 63 20 74 6f 20 31  all traffic to 1
1e00: 32 37 2e 30 2e 30 2e 31 20 6f 6e 6c 79 3b 20 66  27.0.0.1 only; f
1e10: 6f 73 73 69 6c 20 61 6e 64 20 6f 63 78 32 20 72  ossil and ocx2 r
1e20: 75 6e 20 6e 69 63 65 64 3b 20 73 65 72 76 65 72  un niced; server
1e30: 20 73 74 6f 70 70 65 64 20 61 74 20 74 68 65 20   stopped at the 
1e40: 65 6e 64 20 28 73 74 6f 70 2e 73 68 20 70 72 69  end (stop.sh pri
1e50: 6e 74 65 64 20 5c 5c 5c 22 73 74 6f 70 70 65 64  nted \\\"stopped
1e60: 3a 20 6e 6f 74 68 69 6e 67 20 73 65 72 76 65 73  : nothing serves
1e70: 20 2e 2e 2e 2f 70 72 69 76 61 63 79 2f 73 65 72   .../privacy/ser
1e80: 76 65 72 2f 72 65 70 6f 2e 66 6f 73 73 69 6c 5c  ver/repo.fossil\
1e90: 5c 5c 22 20 61 6e 64 20 63 75 72 6c 20 74 6f 20  \\" and curl to 
1ea0: 31 38 39 33 32 20 6e 6f 77 20 72 65 66 75 73 65  18932 now refuse
1eb0: 73 29 2e 20 54 68 65 20 6f 74 68 65 72 20 66 6f  s). The other fo
1ec0: 73 73 69 6c 20 73 65 72 76 65 72 73 20 6f 6e 20  ssil servers on 
1ed0: 31 38 39 33 31 2f 31 38 39 33 33 2f 31 38 39 33  18931/18933/1893
1ee0: 34 20 62 65 6c 6f 6e 67 20 74 6f 20 73 69 62 6c  4 belong to sibl
1ef0: 69 6e 67 20 61 67 65 6e 74 73 27 20 64 69 72 73  ing agents' dirs
1f00: 20 28 63 6f 6e 63 75 72 72 65 6e 63 79 2f 61 75   (concurrency/au
1f10: 74 68 6f 72 69 74 79 2f 69 6e 70 75 74 29 20 61  thority/input) a
1f20: 6e 64 20 77 65 72 65 20 6c 65 66 74 20 75 6e 74  nd were left unt
1f30: 6f 75 63 68 65 64 2e 20 49 20 64 69 64 20 6e 6f  ouched. I did no
1f40: 74 20 63 6f 6d 6d 69 74 2f 73 79 6e 63 20 74 6f  t commit/sync to
1f50: 20 61 6e 79 20 72 65 61 6c 20 73 65 72 76 65 72   any real server
1f60: 2c 20 70 6f 73 74 2c 20 73 74 61 67 65 20 6f 72  , post, stage or
1f70: 20 61 63 63 65 70 74 3b 20 74 68 65 20 74 72 65   accept; the tre
1f80: 65 2c 20 69 74 73 20 63 6c 6f 6e 65 20 61 6e 64  e, its clone and
1f90: 20 73 74 61 67 65 64 2f 6e 65 78 74 20 77 65 72   staged/next wer
1fa0: 65 20 6f 6e 6c 79 20 72 65 61 64 2e 5c 5c 6e 5c  e only read.\\n\
1fb0: 5c 6e 48 65 6c 64 20 28 6e 6f 20 76 69 6f 6c 61  \nHeld (no viola
1fc0: 74 69 6f 6e 20 66 6f 75 6e 64 29 3a 5c 5c 6e 2d  tion found):\\n-
1fd0: 20 50 72 69 76 61 74 65 2d 61 72 74 69 66 61 63   Private-artifac
1fe0: 74 20 66 69 6c 74 65 72 20 69 6e 20 72 65 63 65  t filter in rece
1ff0: 69 70 74 20 68 6f 6c 64 73 3a 20 49 20 63 72 65  ipt holds: I cre
2000: 61 74 65 64 20 61 20 2d 2d 70 72 69 76 61 74 65  ated a --private
2010: 20 63 68 65 63 6b 2d 69 6e 20 28 37 31 34 34 2e   check-in (7144.
2020: 2e 2e 29 20 6f 6e 20 74 68 65 20 73 63 72 61 74  ..) on the scrat
2030: 63 68 20 73 65 72 76 65 72 2e 20 41 73 20 27 6e  ch server. As 'n
2040: 6f 62 6f 64 79 27 20 28 68 6f 6c 64 73 20 6f 2c  obody' (holds o,
2050: 20 6e 6f 74 20 78 29 20 72 65 63 65 69 70 74 20   not x) receipt 
2060: 72 65 74 75 72 6e 73 20 72 65 63 65 69 76 65 64  returns received
2070: 3a 66 61 6c 73 65 3b 20 61 73 20 6f 77 6e 65 72  :false; as owner
2080: 20 28 73 65 74 75 70 2c 20 69 6d 70 6c 69 65 73   (setup, implies
2090: 20 78 29 20 69 74 20 72 65 74 75 72 6e 73 20 72   x) it returns r
20a0: 65 63 65 69 76 65 64 3a 74 72 75 65 20 77 69 74  eceived:true wit
20b0: 68 20 73 65 6e 64 65 72 2f 72 65 63 65 69 70 74  h sender/receipt
20c0: 2e 20 54 68 65 20 78 2d 67 61 74 65 20 69 73 20  . The x-gate is 
20d0: 65 6e 66 6f 72 63 65 64 20 61 74 20 72 65 63 65  enforced at rece
20e0: 69 70 74 2e 63 72 3a 31 35 38 20 61 6e 64 20 74  ipt.cr:158 and t
20f0: 68 72 65 61 64 2e 63 72 3a 39 31 20 28 72 65 6a  hread.cr:91 (rej
2100: 65 63 74 20 70 72 69 76 61 74 65 20 75 6e 6c 65  ect private unle
2110: 73 73 20 50 72 69 76 61 74 65 20 27 78 27 29 2e  ss Private 'x').
2120: 5c 5c 6e 2d 20 75 6e 61 75 64 69 74 65 64 20 6e  \\n- unaudited n
2130: 65 76 65 72 20 6c 69 73 74 73 20 70 72 69 76 61  ever lists priva
2140: 74 65 20 63 68 65 63 6b 2d 69 6e 73 3a 20 63 68  te check-ins: ch
2150: 65 63 6b 69 6e 73 5f 63 68 61 6e 67 69 6e 67 5f  eckins_changing_
2160: 66 69 6c 65 73 20 65 78 63 6c 75 64 65 73 20 60  files excludes `
2170: 70 72 69 76 61 74 65 60 20 69 6e 20 53 51 4c 20  private` in SQL 
2180: 28 66 6f 73 73 69 6c 2f 73 61 69 64 2e 63 72 3a  (fossil/said.cr:
2190: 31 33 31 29 3b 20 63 6f 6e 66 69 72 6d 65 64 20  131); confirmed 
21a0: 74 68 65 20 70 72 69 76 61 74 65 20 63 68 65 63  the private chec
21b0: 6b 2d 69 6e 20 69 73 20 61 62 73 65 6e 74 20 66  k-in is absent f
21c0: 72 6f 6d 20 75 6e 61 75 64 69 74 65 64 20 61 73  rom unaudited as
21d0: 20 6e 6f 62 6f 64 79 2e 5c 5c 6e 2d 20 4e 6f 20   nobody.\\n- No 
21e0: 73 65 63 72 65 74 20 72 65 61 64 2d 62 61 63 6b  secret read-back
21f0: 20 70 61 74 68 20 65 78 69 73 74 73 3a 20 6e 6f   path exists: no
2200: 20 43 47 49 2f 4d 43 50 2f 43 4c 49 20 74 6f 6f   CGI/MCP/CLI too
2210: 6c 20 72 65 74 75 72 6e 73 20 63 6f 6e 66 69 67  l returns config
2220: 20 72 6f 77 73 2e 20 49 20 73 65 74 20 6f 63 78   rows. I set ocx
2230: 2d 73 65 63 72 65 74 2d 74 75 6e 6e 65 6c 3d 53  -secret-tunnel=S
2240: 55 50 45 52 53 45 43 52 45 54 56 41 4c 55 45 34  UPERSECRETVALUE4
2250: 32 20 64 69 72 65 63 74 6c 79 3b 20 69 74 20 61  2 directly; it a
2260: 70 70 65 61 72 73 20 69 6e 20 73 74 61 74 75 73  ppears in status
2270: 3f 20 6e 6f 2c 20 6c 6f 67 73 3f 20 6e 6f 2c 20  ? no, logs? no, 
2280: 6c 69 73 74 20 48 54 4d 4c 3f 20 6e 6f 2e 20 53  list HTML? no. S
2290: 65 63 72 65 74 20 76 61 6c 75 65 73 20 61 72 65  ecret values are
22a0: 20 6f 6e 6c 79 20 72 65 61 64 20 73 65 72 76 65   only read serve
22b0: 72 2d 73 69 64 65 20 62 79 20 74 68 65 20 77 61  r-side by the wa
22c0: 74 63 68 65 72 20 74 6f 20 66 69 6c 6c 20 61 20  tcher to fill a 
22d0: 73 61 6e 64 62 6f 78 65 64 20 72 75 6e 27 73 20  sandboxed run's 
22e0: 65 6e 76 20 28 6c 61 75 6e 63 68 2e 63 72 3a 31  env (launch.cr:1
22f0: 37 31 2c 20 77 61 74 63 68 65 72 2e 63 72 3a 32  71, watcher.cr:2
2300: 38 36 2d 32 39 32 29 3b 20 74 68 65 20 53 65 63  86-292); the Sec
2310: 72 65 74 20 6c 65 61 66 20 72 65 6e 64 65 72 73  ret leaf renders
2320: 20 61 73 20 5c 5c 5c 22 28 68 69 64 64 65 6e 29   as \\\"(hidden)
2330: 5c 5c 5c 22 20 65 76 65 72 79 77 68 65 72 65 20  \\\" everywhere 
2340: 28 65 6c 65 6d 65 6e 74 73 2e 63 72 3a 33 33 35  (elements.cr:335
2350: 2d 33 35 37 29 20 61 6e 64 20 53 65 74 53 65 63  -357) and SetSec
2360: 72 65 74 27 73 20 76 61 6c 75 65 20 69 73 20 4a  ret's value is J
2370: 53 4f 4e 2d 69 67 6e 6f 72 65 64 20 28 73 65 63  SON-ignored (sec
2380: 72 65 74 2e 63 72 3a 31 33 29 2e 5c 5c 6e 2d 20  ret.cr:13).\\n- 
2390: 63 6f 6c 6c 65 63 74 27 73 20 65 72 72 6f 72 20  collect's error 
23a0: 6f 6e 20 61 20 77 72 6f 6e 67 20 63 6f 64 65 20  on a wrong code 
23b0: 64 6f 65 73 20 6e 6f 74 20 65 63 68 6f 20 74 68  does not echo th
23c0: 65 20 63 6f 64 65 20 28 5c 5c 5c 22 74 68 65 20  e code (\\\"the 
23d0: 63 6f 64 65 20 69 73 20 6e 6f 74 20 74 68 65 20  code is not the 
23e0: 6f 6e 65 20 6c 61 62 2d 37 20 77 61 73 20 61 70  one lab-7 was ap
23f0: 70 72 6f 76 65 64 20 66 6f 72 5c 5c 5c 22 29 2e  proved for\\\").
2400: 5c 5c 6e 2d 20 60 6e 61 6d 65 3d 60 20 63 61 6e  \\n- `name=` can
2410: 6e 6f 74 20 73 65 6c 65 63 74 20 66 69 6c 65 73  not select files
2420: 20 6f 75 74 73 69 64 65 20 65 78 74 72 6f 6f 74   outside extroot
2430: 3a 20 6e 61 6d 65 3d 2e 2e 2f 2e 2e 2f 73 65 72  : name=../../ser
2440: 76 65 72 2f 72 65 70 6f 2e 66 6f 73 73 69 6c 20  ver/repo.fossil 
2450: 61 6e 64 20 6e 61 6d 65 3d 2e 2e 2f 77 68 6f 20  and name=../who 
2460: 62 6f 74 68 20 34 30 34 20 28 46 6f 73 73 69 6c  both 404 (Fossil
2470: 20 73 61 6e 69 74 69 7a 65 73 29 2c 20 73 6f 20   sanitizes), so 
2480: 74 68 65 20 6e 61 6d 65 20 63 6f 6c 6c 69 73 69  the name collisi
2490: 6f 6e 20 69 73 20 61 20 62 72 6f 6b 65 6e 20 65  on is a broken e
24a0: 6e 74 72 79 20 70 6f 69 6e 74 2c 20 6e 6f 74 20  ntry point, not 
24b0: 61 20 74 72 61 76 65 72 73 61 6c 2f 72 65 61 64  a traversal/read
24c0: 2e 5c 5c 6e 2d 20 73 61 6d 65 2d 73 69 74 65 20  .\\n- same-site 
24d0: 50 4f 53 54 20 65 6e 66 6f 72 63 65 6d 65 6e 74  POST enforcement
24e0: 20 77 6f 72 6b 73 3a 20 61 70 70 72 6f 76 65 20   works: approve 
24f0: 28 6e 65 65 64 73 20 61 29 20 73 75 63 63 65 65  (needs a) succee
2500: 64 65 64 20 6f 6e 6c 79 20 61 73 20 61 20 50 4f  ded only as a PO
2510: 53 54 20 77 69 74 68 20 61 20 74 68 69 73 2d 73  ST with a this-s
2520: 69 74 65 20 52 65 66 65 72 65 72 2e 5c 5c 6e 2d  ite Referer.\\n-
2530: 20 4e 6f 20 70 61 73 73 77 6f 72 64 2f 73 65 63   No password/sec
2540: 72 65 74 20 61 70 70 65 61 72 73 20 69 6e 20 74  ret appears in t
2550: 68 65 20 6c 69 73 74 20 70 61 67 65 2c 20 73 74  he list page, st
2560: 61 74 75 73 20 4a 53 4f 4e 2c 20 6f 72 20 73 65  atus JSON, or se
2570: 72 76 65 72 2e 6c 6f 67 20 28 67 72 65 70 73 20  rver.log (greps 
2580: 66 6f 72 20 74 68 65 20 6f 77 6e 65 72 20 70 61  for the owner pa
2590: 73 73 77 6f 72 64 2c 20 74 68 65 20 63 6f 6c 6c  ssword, the coll
25a0: 65 63 74 65 64 20 70 61 73 73 77 6f 72 64 2c 20  ected password, 
25b0: 61 6e 64 20 74 68 65 20 73 65 63 72 65 74 20 76  and the secret v
25c0: 61 6c 75 65 20 61 6c 6c 20 65 6d 70 74 79 29 2e  alue all empty).
25d0: 20 73 74 61 74 75 73 20 64 69 73 63 6c 6f 73 65   status disclose
25e0: 73 20 61 62 73 6f 6c 75 74 65 20 73 65 72 76 65  s absolute serve
25f0: 72 20 66 69 6c 65 73 79 73 74 65 6d 20 70 61 74  r filesystem pat
2600: 68 73 20 28 72 65 70 6f 73 69 74 6f 72 79 2f 72  hs (repository/r
2610: 6f 6f 74 2f 64 69 72 29 20 74 6f 20 75 6e 61 75  oot/dir) to unau
2620: 74 68 65 6e 74 69 63 61 74 65 64 20 63 61 6c 6c  thenticated call
2630: 65 72 73 2c 20 62 75 74 20 73 74 61 74 75 73 27  ers, but status'
2640: 73 20 70 75 72 70 6f 73 65 20 69 73 20 74 6f 20  s purpose is to 
2650: 73 68 6f 77 20 74 68 65 20 72 65 70 6f 73 69 74  show the reposit
2660: 6f 72 79 2f 63 68 65 63 6b 6f 75 74 20 61 6e 64  ory/checkout and
2670: 20 74 68 69 73 20 6d 61 74 63 68 65 73 20 66 61   this matches fa
2680: 63 74 73 2e 74 78 74 2c 20 73 6f 20 49 20 64 69  cts.txt, so I di
2690: 64 20 6e 6f 74 20 74 72 65 61 74 20 69 74 20 61  d not treat it a
26a0: 73 20 61 20 66 69 6e 64 69 6e 67 2e 5c 22 7d 22  s a finding.\"}"
26b0: 0a 7d 0a 00 00 00 00 00 00 00 00 00 00 00 00 00  .}..............
26c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
26d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
26e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
26f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2710: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2720: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
27f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2800: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
2810: 2f 61 64 76 65 72 73 61 72 79 2d 74 72 69 61 67  /adversary-triag
2820: 65 2e 6d 64 00 00 00 00 00 00 00 00 00 00 00 00  e.md............
2830: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2840: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2850: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2860: 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
2870: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
2880: 30 30 34 37 33 30 31 00 31 35 32 36 35 32 30 34  0047301.15265204
2890: 32 31 30 00 30 31 36 36 32 35 00 20 30 00 00 00  210.016625. 0...
28a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
28b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
28c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
28d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
28e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
28f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2900: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
2910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2920: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
2930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
29f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
2a00: 23 20 41 64 76 65 72 73 61 72 69 61 6c 20 74 72  # Adversarial tr
2a10: 69 61 67 65 3a 20 31 34 20 63 6f 6e 66 69 72 6d  iage: 14 confirm
2a20: 65 64 20 66 69 6e 64 69 6e 67 73 2c 20 34 20 64  ed findings, 4 d
2a30: 72 6f 70 70 65 64 0a 0a 49 20 72 65 70 72 6f 64  ropped..I reprod
2a40: 75 63 65 64 20 65 76 65 72 79 74 68 69 6e 67 20  uced everything 
2a50: 6f 6e 20 61 20 66 72 65 73 68 20 69 6e 73 74 61  on a fresh insta
2a60: 6e 63 65 20 61 74 20 60 2f 74 6d 70 2f 63 6c 61  nce at `/tmp/cla
2a70: 75 64 65 2d 30 2f 2d 76 61 72 2d 6c 69 62 2d 6f  ude-0/-var-lib-o
2a80: 63 78 2d 61 67 65 6e 74 73 2d 6f 70 75 73 2d 6f  cx-agents-opus-o
2a90: 63 78 32 2d 70 72 6f 6a 65 63 74 73 2d 6f 6c 6c  cx2-projects-oll
2aa0: 61 6d 61 2d 62 32 64 65 38 62 30 63 32 63 36 37  ama-b2de8b0c2c67
2ab0: 30 30 65 62 35 63 36 38 36 62 31 37 34 37 62 35  00eb5c686b1747b5
2ac0: 61 61 61 31 65 32 64 32 64 30 31 33 37 30 61 63  aaa1e2d2d01370ac
2ad0: 35 35 66 32 65 35 61 31 35 31 61 36 37 65 30 33  55f2e5a151a67e03
2ae0: 62 34 38 61 2f 33 66 37 63 66 65 32 35 2d 32 38  b48a/3f7cfe25-28
2af0: 61 61 2d 34 63 35 35 2d 38 32 37 63 2d 62 63 30  aa-4c55-827c-bc0
2b00: 36 31 38 64 61 38 31 65 36 2f 73 63 72 61 74 63  618da81e6/scratc
2b10: 68 70 61 64 2f 61 64 76 65 72 73 61 72 79 2f 74  hpad/adversary/t
2b20: 72 69 61 67 65 60 20 28 44 20 62 65 6c 6f 77 29  riage` (D below)
2b30: 2c 20 6f 6e 20 70 6f 72 74 20 31 38 39 33 35 20  , on port 18935 
2b40: 28 60 55 3d 68 74 74 70 3a 2f 2f 31 32 37 2e 30  (`U=http://127.0
2b50: 2e 30 2e 31 3a 31 38 39 33 35 60 29 2e 20 54 68  .0.1:18935`). Th
2b60: 65 20 70 72 6f 67 72 61 6d 20 69 73 20 74 68 65  e program is the
2b70: 20 73 74 61 67 65 64 20 63 6f 70 79 2c 20 73 68   staged copy, sh
2b80: 61 32 35 36 20 36 61 65 66 38 61 64 37 e2 80 a6  a256 6aef8ad7…
2b90: 2e 0a 0a 2d 20 2a 2a 43 6f 6e 66 69 6e 65 6d 65  ...- **Confineme
2ba0: 6e 74 3a 2a 2a 20 49 20 72 61 6e 20 74 68 65 20  nt:** I ran the 
2bb0: 73 65 72 76 65 72 20 28 60 44 2f 73 74 61 72 74  server (`D/start
2bc0: 2d 63 6f 6e 66 69 6e 65 64 2e 73 68 60 29 20 61  -confined.sh`) a
2bd0: 6e 64 20 65 76 65 72 79 20 6f 63 78 32 20 63 61  nd every ocx2 ca
2be0: 6c 6c 20 28 60 44 2f 63 2e 73 68 60 29 20 75 6e  ll (`D/c.sh`) un
2bf0: 64 65 72 20 60 62 77 72 61 70 20 2d 2d 62 69 6e  der `bwrap --bin
2c00: 64 20 44 2f 61 63 63 74 20 2f 72 6f 6f 74 60 2e  d D/acct /root`.
2c10: 20 54 68 69 73 20 69 73 20 6e 65 65 64 65 64 20   This is needed 
2c20: 62 65 63 61 75 73 65 20 6f 66 20 66 69 6e 64 69  because of findi
2c30: 6e 67 20 31 34 2e 20 60 2f 72 6f 6f 74 2f 2e 66  ng 14. `/root/.f
2c40: 6f 73 73 69 6c 60 20 77 61 73 20 6c 61 73 74 20  ossil` was last 
2c50: 63 68 61 6e 67 65 64 20 61 74 20 31 37 3a 32 37  changed at 17:27
2c60: 20 55 54 43 2c 20 62 65 66 6f 72 65 20 74 68 69   UTC, before thi
2c70: 73 20 74 72 69 61 67 65 20 73 74 61 72 74 65 64  s triage started
2c80: 20 61 74 20 31 37 3a 33 35 2e 0a 2d 20 2a 2a 46   at 17:35..- **F
2c90: 6f 72 63 69 6e 67 20 74 68 65 20 6f 72 64 65 72  orcing the order
2ca0: 20 6f 66 20 65 76 65 6e 74 73 3a 2a 2a 20 60 44   of events:** `D
2cb0: 2f 73 68 69 6d 2f 66 6f 73 73 69 6c 60 20 73 74  /shim/fossil` st
2cc0: 6f 70 73 20 61 20 63 68 6f 73 65 6e 20 66 6f 73  ops a chosen fos
2cd0: 73 69 6c 20 63 6f 6d 6d 61 6e 64 20 75 6e 74 69  sil command unti
2ce0: 6c 20 72 65 6c 65 61 73 65 64 20 28 60 44 2f 67  l released (`D/g
2cf0: 61 74 65 2e 73 68 60 29 2c 20 61 6e 64 20 60 44  ate.sh`), and `D
2d00: 2f 68 6f 6c 64 2e 73 68 60 20 68 6f 6c 64 73 20  /hold.sh` holds 
2d10: 60 42 45 47 49 4e 20 49 4d 4d 45 44 49 41 54 45  `BEGIN IMMEDIATE
2d20: 60 20 74 68 72 6f 75 67 68 20 74 68 65 20 73 71  ` through the sq
2d30: 6c 69 74 65 33 20 63 6f 6d 6d 61 6e 64 2d 6c 69  lite3 command-li
2d40: 6e 65 20 74 6f 6f 6c 2e 20 54 68 65 20 73 63 72  ne tool. The scr
2d50: 69 70 74 73 20 61 72 65 20 60 44 2f 74 4b 2e 73  ipts are `D/tK.s
2d60: 68 60 2c 20 60 44 2f 74 41 2e 73 68 60 2c 20 60  h`, `D/tA.sh`, `
2d70: 44 2f 74 50 2e 73 68 60 20 61 6e 64 20 60 44 2f  D/tP.sh` and `D/
2d80: 74 4d 2e 73 68 60 2e 0a 2d 20 2a 2a 53 68 75 74  tM.sh`..- **Shut
2d90: 64 6f 77 6e 3a 2a 2a 20 74 68 65 20 73 65 72 76  down:** the serv
2da0: 65 72 20 69 73 20 73 74 6f 70 70 65 64 2e 20 60  er is stopped. `
2db0: 73 74 6f 70 2e 73 68 60 20 70 72 69 6e 74 65 64  stop.sh` printed
2dc0: 20 22 73 74 6f 70 70 65 64 3a 20 6e 6f 74 68 69   "stopped: nothi
2dd0: 6e 67 20 73 65 72 76 65 73 20 e2 80 a6 2f 74 72  ng serves …/tr
2de0: 69 61 67 65 2f 73 65 72 76 65 72 2f 72 65 70 6f  iage/server/repo
2df0: 2e 66 6f 73 73 69 6c 22 2c 20 61 6e 64 20 63 75  .fossil", and cu
2e00: 72 6c 20 74 6f 20 31 38 39 33 35 2c 20 31 38 39  rl to 18935, 189
2e10: 34 35 20 61 6e 64 20 31 38 39 34 36 20 65 78 69  45 and 18946 exi
2e20: 74 73 20 37 2e 20 54 68 65 20 4d 43 50 20 48 54  ts 7. The MCP HT
2e30: 54 50 20 73 65 72 76 65 72 2c 20 74 68 65 20 73  TP server, the s
2e40: 74 61 6e 64 2d 69 6e 20 61 6e 64 20 74 68 65 20  tand-in and the 
2e50: 73 71 6c 69 74 65 20 68 6f 6c 64 65 72 20 61 72  sqlite holder ar
2e60: 65 20 61 6c 6c 20 67 6f 6e 65 2e 0a 0a 23 23 20  e all gone...## 
2e70: 43 6f 6e 66 69 72 6d 65 64 20 66 69 6e 64 69 6e  Confirmed findin
2e80: 67 73 2c 20 6d 6f 73 74 20 73 65 76 65 72 65 20  gs, most severe 
2e90: 66 69 72 73 74 0a 0a 7c 20 23 20 7c 20 53 65 76  first..| # | Sev
2ea0: 20 7c 20 46 69 6e 64 69 6e 67 20 28 6d 65 72 67   | Finding (merg
2eb0: 65 64 20 66 72 6f 6d 29 20 7c 20 52 65 70 72 6f  ed from) | Repro
2ec0: 64 75 63 74 69 6f 6e 20 6f 6e 20 74 72 69 61 67  duction on triag
2ed0: 65 20 e2 86 92 20 77 68 61 74 20 63 61 6d 65 20  e → what came 
2ee0: 62 61 63 6b 20 7c 20 53 6d 61 6c 6c 65 73 74 20  back | Smallest 
2ef0: 66 69 78 20 7c 20 53 70 65 63 20 74 68 61 74 20  fix | Spec that 
2f00: 73 68 6f 77 73 20 69 74 20 7c 0a 7c 2d 2d 2d 7c  shows it |.|---|
2f10: 2d 2d 2d 7c 2d 2d 2d 7c 2d 2d 2d 7c 2d 2d 2d 7c  ---|---|---|---|
2f20: 2d 2d 2d 7c 0a 7c 20 31 20 7c 20 68 69 67 68 20  ---|.| 1 | high 
2f30: 7c 20 2a 2a 41 20 66 6f 72 75 6d 20 77 72 69 74  | **A forum writ
2f40: 65 20 63 61 6e 20 62 65 20 73 74 6f 72 65 64 20  e can be stored 
2f50: 62 75 74 20 6e 65 76 65 72 20 69 6e 64 65 78 65  but never indexe
2f60: 64 2e 2a 2a 20 53 65 65 6e 20 6f 6e 20 74 68 65  d.** Seen on the
2f70: 20 73 65 72 76 65 64 20 72 65 70 6f 73 69 74 6f   served reposito
2f80: 72 79 20 28 63 72 65 61 74 65 2c 20 61 20 6e 6f  ry (create, a no
2f90: 64 65 27 73 20 72 65 70 6f 72 74 29 20 61 6e 64  de's report) and
2fa0: 20 69 6e 20 61 20 63 6c 6f 6e 65 20 28 70 6f 73   in a clone (pos
2fb0: 74 29 2e 20 54 68 65 20 61 6e 73 77 65 72 20 67  t). The answer g
2fc0: 69 76 65 73 20 6e 6f 20 68 61 73 68 2e 20 43 6c  ives no hash. Cl
2fd0: 6f 6e 65 73 20 61 6e 64 20 6e 6f 64 65 73 20 61  ones and nodes a
2fe0: 63 74 20 6f 6e 20 74 68 65 20 77 72 69 74 65 2c  ct on the write,
2ff0: 20 61 6e 64 20 61 20 72 65 74 72 79 20 70 6f 73   and a retry pos
3000: 74 73 20 74 77 69 63 65 2e 20 28 43 6f 6e 63 75  ts twice. (Concu
3010: 72 72 65 6e 63 79 20 66 69 6e 64 69 6e 67 73 20  rrency findings 
3020: 31 2c 20 32 20 61 6e 64 20 34 20 6d 65 72 67 65  1, 2 and 4 merge
3030: 64 2e 29 20 7c 20 2a 2a 53 65 72 76 65 64 20 72  d.) | **Served r
3040: 65 70 6f 73 69 74 6f 72 79 20 28 60 74 4b 2e 73  epository (`tK.s
3050: 68 60 29 3a 2a 2a 20 67 61 74 65 20 6f 6e 20 60  h`):** gate on `
3060: 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 60 2c  test-crosslink`,
3070: 20 68 6f 6c 64 20 60 72 65 70 6f 2e 66 6f 73 73   hold `repo.foss
3080: 69 6c 60 2c 20 74 68 65 6e 20 60 63 2e 73 68 20  il`, then `c.sh 
3090: 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 2d 2d 72 65  ocx2 --json --re
30a0: 70 6f 73 69 74 6f 72 79 20 24 52 45 50 4f 20 2d  pository $REPO -
30b0: 2d 75 73 65 72 20 6f 77 6e 65 72 20 63 72 65 61  -user owner crea
30c0: 74 65 20 22 52 75 6e 20 4b e2 80 a6 22 20 2d 2d  te "Run K…" --
30d0: 6e 6f 64 65 20 6e 6f 64 65 41 20 2d 2d 66 69 65  node nodeA --fie
30e0: 6c 64 73 20 27 7b 22 70 72 6f 63 65 73 73 22 3a  lds '{"process":
30f0: 7b 22 75 73 65 72 22 3a 22 6f 74 74 6f 22 2c 22  {"user":"otto","
3100: 63 6f 6d 6d 61 6e 64 22 3a 5b 22 74 72 75 65 22  command":["true"
3110: 5d 7d 7d 27 60 2e 20 49 74 20 61 6e 73 77 65 72  ]}}'`. It answer
3120: 65 64 20 6f 6b 3a 66 61 6c 73 65 20 77 69 74 68  ed ok:false with
3130: 20 6e 6f 20 72 65 73 75 6c 74 3a 20 22 66 6f 73   no result: "fos
3140: 73 69 6c 20 74 65 73 74 2d 63 72 6f 73 73 6c 69  sil test-crossli
3150: 6e 6b 20 6f 6e 20 e2 80 a6 72 65 70 6f 2e 66 6f  nk on …repo.fo
3160: 73 73 69 6c 3a 20 61 20 77 72 69 74 65 72 20 6f  ssil: a writer o
3170: 75 74 73 69 64 65 20 4f 43 58 20 68 65 6c 64 20  utside OCX held 
3180: e2 80 a6 20 77 68 61 74 20 61 6e 20 65 61 72 6c  … what an earl
3190: 69 65 72 20 63 6f 6d 6d 61 6e 64 20 77 72 6f 74  ier command wrot
31a0: 65 20 73 74 61 79 73 3a 20 e2 80 a6 52 45 50 4c  e stays: …REPL
31b0: 41 43 45 20 49 4e 54 4f 20 66 6f 72 75 6d 70 6f  ACE INTO forumpo
31c0: 73 74 e2 80 a6 22 2e 20 54 68 65 20 73 65 72 76  st…". The serv
31d0: 65 72 20 6b 65 65 70 73 20 72 69 64 20 31 38 20  er keeps rid 18 
31e0: 3d 20 38 37 33 30 36 64 65 39 e2 80 a6 20 77 69  = 87306de9… wi
31f0: 74 68 20 30 20 66 6f 72 75 6d 70 6f 73 74 20 61  th 0 forumpost a
3200: 6e 64 20 30 20 65 76 65 6e 74 20 72 6f 77 73 2e  nd 0 event rows.
3210: 20 4f 6e 20 74 68 65 20 73 65 72 76 65 72 2c 20   On the server, 
3220: 60 74 68 72 65 61 64 20 38 37 33 30 36 64 65 39  `thread 87306de9
3230: 60 20 61 6e 73 77 65 72 73 20 22 6e 61 6d 65 73  ` answers "names
3240: 20 6e 6f 20 74 69 63 6b 65 74 20 6f 72 20 66 6f   no ticket or fo
3250: 72 75 6d 20 74 68 72 65 61 64 22 2e 20 41 66 74  rum thread". Aft
3260: 65 72 20 60 66 6f 73 73 69 6c 20 70 75 6c 6c 60  er `fossil pull`
3270: 2c 20 69 76 79 27 73 20 63 6c 6f 6e 65 20 69 6e  , ivy's clone in
3280: 64 65 78 65 73 20 69 74 20 28 31 2f 31 29 2c 20  dexes it (1/1), 
3290: 61 6e 64 20 69 74 73 20 60 74 68 72 65 61 64 20  and its `thread 
32a0: 38 37 33 30 36 64 65 39 60 20 6c 69 73 74 73 20  87306de9` lists 
32b0: 6f 77 6e 65 72 27 73 20 72 75 6e 2e 20 2a 2a 43  owner's run. **C
32c0: 6c 6f 6e 65 20 28 60 74 41 2e 73 68 20 74 65 73  lone (`tA.sh tes
32d0: 74 2d 63 72 6f 73 73 6c 69 6e 6b 20 63 36 62 35  t-crosslink c6b5
32e0: 66 30 35 63 20 22 72 65 70 6c 79 20 41 e2 80 a6  f05c "reply A…
32f0: 22 60 29 3a 2a 2a 20 6f 6b 3a 66 61 6c 73 65 2c  "`):** ok:false,
3300: 20 61 6e 64 20 72 69 64 20 31 39 20 3d 20 38 37   and rid 19 = 87
3310: 38 30 62 30 61 63 e2 80 a6 20 69 73 20 6c 65 66  80b0ac… is lef
3320: 74 20 75 6e 69 6e 64 65 78 65 64 2e 20 41 20 72  t unindexed. A r
3330: 65 74 72 79 20 61 6e 73 77 65 72 65 64 20 6f 6b  etry answered ok
3340: 2c 20 77 72 69 74 74 65 6e 20 36 31 34 65 30 32  , written 614e02
3350: 39 64 e2 80 a6 2e 20 54 68 65 20 73 65 72 76 65  9d…. The serve
3360: 72 20 74 68 72 65 61 64 20 74 68 65 6e 20 68 6f  r thread then ho
3370: 6c 64 73 20 62 6f 74 68 20 36 31 34 65 30 32 39  lds both 614e029
3380: 64 20 61 6e 64 20 38 37 38 30 62 30 61 63 2e 20  d and 8780b0ac. 
3390: 54 68 65 20 63 6c 6f 6e 65 27 73 20 74 68 72 65  The clone's thre
33a0: 61 64 20 73 68 6f 77 73 20 6f 6e 6c 79 20 36 31  ad shows only 61
33b0: 34 65 30 32 39 64 2c 20 65 76 65 6e 20 61 66 74  4e029d, even aft
33c0: 65 72 20 61 20 70 75 6c 6c 2e 20 2a 2a 4e 6f 64  er a pull. **Nod
33d0: 65 20 28 60 74 50 2e 73 68 60 29 3a 2a 2a 20 72  e (`tP.sh`):** r
33e0: 75 6e 20 61 37 33 39 31 37 37 62 20 77 61 73 20  un a739177b was 
33f0: 63 72 65 61 74 65 64 20 66 6f 72 20 6e 6f 64 65  created for node
3400: 61 2c 20 61 6e 64 20 74 68 65 20 70 6f 6c 6c 20  a, and the poll 
3410: 77 61 73 20 68 65 6c 64 20 61 74 20 63 72 6f 73  was held at cros
3420: 73 6c 69 6e 6b 2e 20 54 68 61 74 20 70 6f 6c 6c  slink. That poll
3430: 20 61 6e 73 77 65 72 65 64 20 6f 6b 3a 66 61 6c   answered ok:fal
3440: 73 65 20 61 6e 64 20 61 64 64 65 64 20 6e 6f 20  se and added no 
3450: 68 6f 6f 6b 2e 6c 6f 67 20 6c 69 6e 65 2e 20 54  hook.log line. T
3460: 68 65 20 6e 65 78 74 20 6f 72 64 69 6e 61 72 79  he next ordinary
3470: 20 70 6f 6c 6c 20 61 6e 73 77 65 72 65 64 20 61   poll answered a
3480: 72 74 69 66 61 63 74 73 20 5b 5d 2c 20 61 6e 73  rtifacts [], ans
3490: 77 65 72 65 64 20 5b 5d 2e 20 60 70 6f 6c 6c 20  wered []. `poll 
34a0: 2d 2d 63 68 65 63 6b 60 20 74 68 65 6e 20 77 72  --check` then wr
34b0: 6f 74 65 20 61 20 73 65 63 6f 6e 64 20 72 65 70  ote a second rep
34c0: 6f 72 74 2e 20 54 68 65 20 73 65 72 76 65 72 20  ort. The server 
34d0: 74 68 72 65 61 64 20 61 37 33 39 31 37 37 62 20  thread a739177b 
34e0: 6e 6f 77 20 68 61 73 20 74 77 6f 20 60 22 65 6e  now has two `"en
34f0: 64 65 64 22 60 20 70 6f 73 74 73 20 66 72 6f 6d  ded"` posts from
3500: 20 6e 6f 64 65 61 3a 20 30 64 61 62 39 66 32 34   nodea: 0dab9f24
3510: 20 61 6e 64 20 39 61 62 36 38 37 38 37 2e 20 7c   and 9ab68787. |
3520: 20 49 6e 20 60 73 72 63 2f 6f 63 78 2f 66 6f 73   In `src/ocx/fos
3530: 73 69 6c 2f 66 6f 72 75 6d 2e 63 72 60 20 60 70  sil/forum.cr` `p
3540: 75 74 5f 70 6f 73 74 60 20 28 6c 69 6e 65 73 20  ut_post` (lines 
3550: 39 39 e2 80 93 31 31 30 29 2c 20 77 72 61 70 20  99–110), wrap 
3560: 60 72 75 6e 28 5b 22 74 65 73 74 2d 63 72 6f 73  `run(["test-cros
3570: 73 6c 69 6e 6b 22 2c 20 68 61 73 68 5d 29 60 20  slink", hash])` 
3580: 69 6e 20 61 20 72 65 73 63 75 65 20 6f 66 20 60  in a rescue of `
3590: 46 61 69 6c 65 64 60 2e 20 49 74 20 73 68 6f 75  Failed`. It shou
35a0: 6c 64 20 72 61 69 73 65 20 61 20 60 46 61 69 6c  ld raise a `Fail
35b0: 65 64 60 20 74 68 61 74 20 6e 61 6d 65 73 20 60  ed` that names `
35c0: 68 61 73 68 60 20 61 6e 64 20 73 61 79 73 20 69  hash` and says i
35d0: 74 20 69 73 20 73 74 6f 72 65 64 20 62 75 74 20  t is stored but 
35e0: 6e 6f 74 20 69 6e 64 65 78 65 64 2c 20 61 6e 64  not indexed, and
35f0: 20 74 68 61 74 20 60 66 6f 73 73 69 6c 20 74 65   that `fossil te
3600: 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 20 48 41 53  st-crosslink HAS
3610: 48 20 2d 52 20 52 45 50 4f 60 20 28 6f 72 20 74  H -R REPO` (or t
3620: 68 65 20 73 61 6d 65 20 74 6f 6f 6c 20 72 75 6e  he same tool run
3630: 20 61 67 61 69 6e 29 20 69 6e 64 65 78 65 73 20   again) indexes 
3640: 69 74 2e 20 41 6c 73 6f 20 6d 61 6b 65 20 60 70  it. Also make `p
3650: 75 74 5f 70 6f 73 74 60 20 6d 65 6e 64 20 62 65  ut_post` mend be
3660: 66 6f 72 65 20 69 74 20 77 72 69 74 65 73 3a 20  fore it writes: 
3670: 63 72 6f 73 73 6c 69 6e 6b 20 61 20 62 6c 6f 62  crosslink a blob
3680: 20 74 68 61 74 20 69 73 20 61 6c 72 65 61 64 79   that is already
3690: 20 74 68 65 72 65 20 77 69 74 68 20 74 68 61 74   there with that
36a0: 20 68 61 73 68 20 61 6e 64 20 68 61 73 20 6e 6f   hash and has no
36b0: 20 60 66 6f 72 75 6d 70 6f 73 74 60 20 72 6f 77   `forumpost` row
36c0: 2c 20 69 6e 73 74 65 61 64 20 6f 66 20 70 75 74  , instead of put
36d0: 74 69 6e 67 20 69 74 20 61 67 61 69 6e 2e 20 49  ting it again. I
36e0: 6e 20 60 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61  n `src/ocx/comma
36f0: 6e 64 73 2f 70 6f 6c 6c 2e 63 72 3a 38 33 2d 38  nds/poll.cr:83-8
3700: 37 60 2c 20 61 70 70 65 6e 64 20 74 68 65 20 60  7`, append the `
3710: 48 6f 6f 6b 3a 3a 52 75 6e 60 20 6c 69 6e 65 20  Hook::Run` line 
3720: 6f 6e 20 61 20 66 61 69 6c 65 64 20 72 6f 75 6e  on a failed roun
3730: 64 20 74 6f 6f 2c 20 77 69 74 68 20 69 74 73 20  d too, with its 
3740: 72 65 61 73 6f 6e 2e 20 7c 20 60 73 70 65 63 2f  reason. | `spec/
3750: 6f 63 78 2f 70 6f 73 74 5f 73 70 65 63 2e 63 72  ocx/post_spec.cr
3760: 60 20 61 6e 64 20 60 73 70 65 63 2f 6f 63 78 2f  ` and `spec/ocx/
3770: 63 72 65 61 74 65 5f 73 70 65 63 2e 63 72 60 3a  create_spec.cr`:
3780: 20 77 69 74 68 20 61 20 73 68 69 6d 20 74 68 61   with a shim tha
3790: 74 20 66 61 69 6c 73 20 60 74 65 73 74 2d 63 72  t fails `test-cr
37a0: 6f 73 73 6c 69 6e 6b 60 20 6f 6e 63 65 2c 20 74  osslink` once, t
37b0: 68 65 20 72 65 66 75 73 61 6c 20 6e 61 6d 65 73  he refusal names
37c0: 20 74 68 65 20 73 74 6f 72 65 64 20 68 61 73 68   the stored hash
37d0: 2c 20 61 6e 64 20 74 68 65 20 6e 65 78 74 20 63  , and the next c
37e0: 61 6c 6c 20 6c 65 61 76 65 73 20 65 78 61 63 74  all leaves exact
37f0: 6c 79 20 6f 6e 65 20 69 6e 64 65 78 65 64 20 70  ly one indexed p
3800: 6f 73 74 2e 20 60 73 70 65 63 2f 6f 63 78 2f 72  ost. `spec/ocx/r
3810: 65 6d 6f 74 65 5f 6e 6f 64 65 5f 73 70 65 63 2e  emote_node_spec.
3820: 63 72 60 3a 20 74 68 65 20 72 65 70 6f 72 74 27  cr`: the report'
3830: 73 20 63 72 6f 73 73 6c 69 6e 6b 20 66 61 69 6c  s crosslink fail
3840: 73 2c 20 74 68 65 6e 20 60 70 6f 6c 6c 20 2d 2d  s, then `poll --
3850: 63 68 65 63 6b 60 20 77 72 69 74 65 73 20 6e 6f  check` writes no
3860: 20 73 65 63 6f 6e 64 20 60 65 6e 64 65 64 60 20   second `ended` 
3870: 61 6e 64 20 68 6f 6f 6b 2e 6c 6f 67 20 68 61 73  and hook.log has
3880: 20 61 20 6c 69 6e 65 20 66 6f 72 20 74 68 65 20   a line for the 
3890: 66 61 69 6c 65 64 20 72 6f 75 6e 64 2e 20 7c 0a  failed round. |.
38a0: 7c 20 32 20 7c 20 68 69 67 68 20 7c 20 2a 2a 65  | 2 | high | **e
38b0: 64 69 74 20 77 72 69 74 65 73 20 6f 75 74 73 69  dit writes outsi
38c0: 64 65 20 74 68 65 20 63 68 65 63 6b 6f 75 74 20  de the checkout 
38d0: 74 68 72 6f 75 67 68 20 61 20 64 61 6e 67 6c 69  through a dangli
38e0: 6e 67 20 73 79 6d 6c 69 6e 6b 2e 2a 2a 20 28 49  ng symlink.** (I
38f0: 6e 70 75 74 20 66 69 6e 64 69 6e 67 20 34 2e 29  nput finding 4.)
3900: 20 7c 20 60 63 64 20 44 2f 63 6c 6f 6e 65 73 2f   | `cd D/clones/
3910: 69 76 79 2f 74 72 65 65 3b 20 6c 6e 20 2d 73 20  ivy/tree; ln -s 
3920: 44 2f 74 2f 4f 55 54 53 49 44 45 2d 77 72 69 74  D/t/OUTSIDE-writ
3930: 74 65 6e 2e 74 78 74 20 64 61 6e 67 6c 69 6e 67  ten.txt dangling
3940: 3b 20 63 2e 73 68 20 6f 63 78 32 20 2d 2d 6a 73  ; c.sh ocx2 --js
3950: 6f 6e 20 65 64 69 74 20 64 61 6e 67 6c 69 6e 67  on edit dangling
3960: 20 22 22 20 22 70 6c 61 6e 74 65 64 20 6f 75 74   "" "planted out
3970: 73 69 64 65 22 60 20 61 6e 73 77 65 72 65 64 20  side"` answered 
3980: 6f 6b 3a 74 72 75 65 2c 20 60 77 72 69 74 65 5f  ok:true, `write_
3990: 66 69 6c 65 20 e2 80 a6 20 62 79 74 65 73 20 31  file … bytes 1
39a0: 35 60 2e 20 60 44 2f 74 2f 4f 55 54 53 49 44 45  5`. `D/t/OUTSIDE
39b0: 2d 77 72 69 74 74 65 6e 2e 74 78 74 60 20 6e 6f  -written.txt` no
39c0: 77 20 68 6f 6c 64 73 20 22 70 6c 61 6e 74 65 64  w holds "planted
39d0: 20 6f 75 74 73 69 64 65 22 2e 20 46 6f 72 20 63   outside". For c
39e0: 6f 6e 74 72 61 73 74 2c 20 60 72 65 61 64 20 6c  ontrast, `read l
39f0: 69 76 65 60 2c 20 77 68 65 72 65 20 6c 69 76 65  ive`, where live
3a00: 20 6c 69 6e 6b 73 20 74 6f 20 61 6e 20 65 78 69   links to an exi
3a10: 73 74 69 6e 67 20 6f 75 74 73 69 64 65 20 66 69  sting outside fi
3a20: 6c 65 2c 20 61 6e 73 77 65 72 73 20 22 6c 69 76  le, answers "liv
3a30: 65 20 6c 65 61 64 73 20 6f 75 74 73 69 64 65 20  e leads outside 
3a40: 74 68 65 20 63 68 65 63 6b 6f 75 74 22 2e 20 7c  the checkout". |
3a50: 20 49 6e 20 60 73 72 63 2f 6f 63 78 2f 63 68 65   In `src/ocx/che
3a60: 63 6b 6f 75 74 5f 66 69 6c 65 73 2e 63 72 60 20  ckout_files.cr` 
3a70: 60 69 6e 73 69 64 65 21 60 20 28 6c 69 6e 65 73  `inside!` (lines
3a80: 20 34 33 e2 80 93 34 35 29 2c 20 69 6e 73 69 64   43–45), insid
3a90: 65 20 74 68 65 20 60 77 68 69 6c 65 20 21 46 69  e the `while !Fi
3aa0: 6c 65 2e 65 78 69 73 74 73 3f 28 65 78 69 73 74  le.exists?(exist
3ab0: 69 6e 67 29 60 20 6c 6f 6f 70 2c 20 72 61 69 73  ing)` loop, rais
3ac0: 65 20 60 52 65 66 75 73 65 64 2e 6e 65 77 28 22  e `Refused.new("
3ad0: 23 7b 70 61 74 68 7d 20 6c 65 61 64 73 20 6f 75  #{path} leads ou
3ae0: 74 73 69 64 65 20 74 68 65 20 63 68 65 63 6b 6f  tside the checko
3af0: 75 74 22 29 60 20 69 66 20 60 46 69 6c 65 2e 73  ut")` if `File.s
3b00: 79 6d 6c 69 6e 6b 3f 28 65 78 69 73 74 69 6e 67  ymlink?(existing
3b10: 29 60 2e 20 41 20 64 61 6e 67 6c 69 6e 67 20 6c  )`. A dangling l
3b20: 69 6e 6b 20 69 73 20 74 68 65 6e 20 72 65 66 75  ink is then refu
3b30: 73 65 64 20 69 6e 73 74 65 61 64 20 6f 66 20 70  sed instead of p
3b40: 61 73 73 65 64 20 6f 76 65 72 2e 20 7c 20 60 73  assed over. | `s
3b50: 70 65 63 2f 6f 63 78 2f 63 68 65 63 6b 6f 75 74  pec/ocx/checkout
3b60: 5f 74 6f 6f 6c 73 5f 73 70 65 63 2e 63 72 60 3a  _tools_spec.cr`:
3b70: 20 60 65 64 69 74 60 20 6f 6e 20 61 20 64 61 6e   `edit` on a dan
3b80: 67 6c 69 6e 67 20 6c 69 6e 6b 2c 20 61 6e 64 20  gling link, and 
3b90: 6f 6e 20 61 20 70 61 74 68 20 75 6e 64 65 72 20  on a path under 
3ba0: 61 20 64 61 6e 67 6c 69 6e 67 20 64 69 72 65 63  a dangling direc
3bb0: 74 6f 72 79 20 6c 69 6e 6b 2c 20 69 73 20 72 65  tory link, is re
3bc0: 66 75 73 65 64 2c 20 61 6e 64 20 74 68 65 20 74  fused, and the t
3bd0: 61 72 67 65 74 20 69 73 20 6e 6f 74 20 63 72 65  arget is not cre
3be0: 61 74 65 64 2e 20 7c 0a 7c 20 33 20 7c 20 68 69  ated. |.| 3 | hi
3bf0: 67 68 20 7c 20 2a 2a 54 65 78 74 20 74 68 61 74  gh | **Text that
3c00: 20 69 73 20 6e 6f 74 20 55 54 46 2d 38 2c 20 6f   is not UTF-8, o
3c10: 72 20 74 68 61 74 20 68 6f 6c 64 73 20 61 20 4e  r that holds a N
3c20: 55 4c 2c 20 67 65 74 73 20 6e 6f 20 72 65 61 73  UL, gets no reas
3c30: 6f 6e 65 64 20 72 65 66 75 73 61 6c 2e 2a 2a 20  oned refusal.** 
3c40: 49 6e 76 61 6c 69 64 20 55 54 46 2d 38 20 6d 61  Invalid UTF-8 ma
3c50: 6b 65 73 20 74 68 65 20 43 47 49 20 63 72 61 73  kes the CGI cras
3c60: 68 3a 20 46 6f 73 73 69 6c 20 61 6e 73 77 65 72  h: Fossil answer
3c70: 73 20 60 32 30 30 20 61 70 70 6c 69 63 61 74 69  s `200 applicati
3c80: 6f 6e 2f 78 2d 66 6f 73 73 69 6c 2d 61 72 74 69  on/x-fossil-arti
3c90: 66 61 63 74 20 30 60 2e 20 41 20 4e 55 4c 20 6d  fact 0`. A NUL m
3ca0: 61 6b 65 73 20 74 68 65 20 72 65 66 75 73 61 6c  akes the refusal
3cb0: 20 63 61 72 72 79 20 61 20 33 33 2d 6c 69 6e 65   carry a 33-line
3cc0: 20 43 72 79 73 74 61 6c 20 62 61 63 6b 74 72 61   Crystal backtra
3cd0: 63 65 20 77 69 74 68 20 61 62 73 6f 6c 75 74 65  ce with absolute
3ce0: 20 70 61 74 68 73 2c 20 73 65 6e 74 20 74 6f 20   paths, sent to 
3cf0: 61 6e 6f 6e 79 6d 6f 75 73 20 75 73 65 72 73 2e  anonymous users.
3d00: 20 28 49 6e 70 75 74 20 66 69 6e 64 69 6e 67 73   (Input findings
3d10: 20 31 20 61 6e 64 20 33 20 6d 65 72 67 65 64 2e   1 and 3 merged.
3d20: 29 20 7c 20 60 63 75 72 6c 20 2d 73 20 2d 77 20  ) | `curl -s -w 
3d30: 27 25 7b 68 74 74 70 5f 63 6f 64 65 7d 20 25 7b  '%{http_code} %{
3d40: 63 6f 6e 74 65 6e 74 5f 74 79 70 65 7d 20 25 7b  content_type} %{
3d50: 73 69 7a 65 5f 64 6f 77 6e 6c 6f 61 64 7d 27 20  size_download}' 
3d60: 22 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69  "$U/ext/ocx2-cgi
3d70: 2f 72 65 63 65 69 70 74 3f 6a 73 6f 6e 3d 6f 6e  /receipt?json=on
3d80: 26 61 72 74 69 66 61 63 74 73 3d 25 66 66 22 60  &artifacts=%ff"`
3d90: 20 67 61 76 65 20 60 32 30 30 20 61 70 70 6c 69   gave `200 appli
3da0: 63 61 74 69 6f 6e 2f 78 2d 66 6f 73 73 69 6c 2d  cation/x-fossil-
3db0: 61 72 74 69 66 61 63 74 20 30 60 2e 20 54 68 65  artifact 0`. The
3dc0: 20 73 61 6d 65 20 68 61 70 70 65 6e 65 64 20 66   same happened f
3dd0: 6f 72 20 60 72 65 63 65 69 70 74 3f 61 72 74 69  or `receipt?arti
3de0: 66 61 63 74 73 3d 25 66 66 60 20 28 74 68 65 20  facts=%ff` (the 
3df0: 70 61 67 65 29 2c 20 66 6f 72 20 60 63 72 65 61  page), for `crea
3e00: 74 65 3f 6a 73 6f 6e 3d 6f 6e 26 64 72 79 5f 72  te?json=on&dry_r
3e10: 75 6e 3d 74 72 75 65 26 6f 62 6a 65 63 74 69 76  un=true&objectiv
3e20: 65 3d 78 26 6e 6f 64 65 3d 25 66 66 60 20 61 73  e=x&node=%ff` as
3e30: 20 6f 77 6e 65 72 2c 20 66 6f 72 20 61 20 50 4f   owner, for a PO
3e40: 53 54 20 6f 66 20 60 73 65 63 72 65 74 60 20 77  ST of `secret` w
3e50: 69 74 68 20 60 6e 61 6d 65 3d 25 66 66 60 20 61  ith `name=%ff` a
3e60: 73 20 6f 77 6e 65 72 2c 20 61 6e 64 20 66 6f 72  s owner, and for
3e70: 20 60 61 70 70 72 6f 76 65 3f e2 80 a6 26 63 61   `approve?…&ca
3e80: 70 61 62 69 6c 69 74 69 65 73 3d 25 66 66 60 2e  pabilities=%ff`.
3e90: 20 73 65 72 76 65 72 2e 6c 6f 67 20 68 61 73 20   server.log has 
3ea0: 35 c3 97 20 22 55 6e 68 61 6e 64 6c 65 64 20 65  5× "Unhandled e
3eb0: 78 63 65 70 74 69 6f 6e 3a 20 52 65 67 65 78 20  xception: Regex 
3ec0: 6d 61 74 63 68 20 65 72 72 6f 72 3a 20 55 54 46  match error: UTF
3ed0: 2d 38 20 65 72 72 6f 72 3a 20 69 6c 6c 65 67 61  -8 error: illega
3ee0: 6c 20 62 79 74 65 20 28 30 78 66 65 20 6f 72 20  l byte (0xfe or 
3ef0: 30 78 66 66 29 22 2e 20 54 68 65 20 63 72 61 73  0xff)". The cras
3f00: 68 65 73 20 61 72 65 20 69 6e 20 52 65 63 65 69  hes are in Recei
3f10: 70 74 43 6f 6d 6d 61 6e 64 2e 72 75 6e 2c 20 4d  ptCommand.run, M
3f20: 65 73 73 61 67 65 73 2e 62 6c 6f 63 6b 73 20 28  essages.blocks (
3f30: 76 69 61 20 43 72 65 61 74 65 43 6f 6d 6d 61 6e  via CreateComman
3f40: 64 2e 77 72 69 74 74 65 6e 29 2c 20 53 65 63 72  d.written), Secr
3f50: 65 74 43 6f 6d 6d 61 6e 64 2e 72 75 6e 20 61 6e  etCommand.run an
3f60: 64 20 43 61 70 61 62 69 6c 69 74 69 65 73 2e 70  d Capabilities.p
3f70: 61 72 73 65 2e 20 60 63 75 72 6c 20 22 24 55 2f  arse. `curl "$U/
3f80: 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f 72 65 63  ext/ocx2-cgi/rec
3f90: 65 69 70 74 3f 6a 73 6f 6e 3d 6f 6e 26 63 61 70  eipt?json=on&cap
3fa0: 61 62 69 6c 69 74 69 65 73 5f 6f 66 3d 61 25 30  abilities_of=a%0
3fb0: 30 62 22 60 20 67 61 76 65 20 34 30 33 2c 20 77  0b"` gave 403, w
3fc0: 69 74 68 20 60 73 74 6f 70 70 65 64 60 20 33 33  ith `stopped` 33
3fd0: 20 6c 69 6e 65 73 20 6c 6f 6e 67 3a 20 22 72 65   lines long: "re
3fe0: 61 64 5f 63 61 70 61 62 69 6c 69 74 69 65 73 20  ad_capabilities 
3ff0: 66 61 69 6c 65 64 3a 20 45 72 72 6f 72 20 65 78  failed: Error ex
4000: 65 63 75 74 69 6e 67 20 70 72 6f 63 65 73 73 3a  ecuting process:
4010: 20 27 66 6f 73 73 69 6c 27 3a 20 53 74 72 69 6e   'fossil': Strin
4020: 67 20 63 6f 6e 74 61 69 6e 73 20 6e 75 6c 6c 20  g contains null 
4030: 62 79 74 65 20 28 41 72 67 75 6d 65 6e 74 45 72  byte (ArgumentEr
4040: 72 6f 72 29 5c 6e 20 20 66 72 6f 6d 20 e2 80 a6  ror)\n  from …
4050: 2f 74 72 69 61 67 65 2f 65 78 74 2f 6f 63 78 32  /triage/ext/ocx2
4060: 2d 63 67 69 20 69 6e 20 27 45 78 63 65 70 74 69  -cgi in 'Excepti
4070: 6f 6e 3a 3a 43 61 6c 6c 53 74 61 63 6b 3a 3a 75  on::CallStack::u
4080: 6e 77 69 6e 64 e2 80 a6 27 22 2e 20 60 75 6e 61  nwind…'". `una
4090: 75 64 69 74 65 64 3f 6a 73 6f 6e 3d 6f 6e 26 62  udited?json=on&b
40a0: 72 61 6e 63 68 3d 25 30 30 60 20 67 61 76 65 20  ranch=%00` gave 
40b0: 74 68 65 20 73 61 6d 65 20 33 33 20 6c 69 6e 65  the same 33 line
40c0: 73 2e 20 7c 20 31 2e 20 49 6e 20 60 73 72 63 2f  s. | 1. In `src/
40d0: 6f 63 78 2f 63 6f 6d 6d 61 6e 64 2e 63 72 60 2c  ocx/command.cr`,
40e0: 20 61 74 20 74 68 65 20 73 74 61 72 74 20 6f 66   at the start of
40f0: 20 62 6f 74 68 20 60 73 65 6c 66 2e 72 65 61 64   both `self.read
4100: 60 20 6f 76 65 72 6c 6f 61 64 73 20 28 6c 69 6e  ` overloads (lin
4110: 65 73 20 32 32 36 20 61 6e 64 20 32 33 30 29 2c  es 226 and 230),
4120: 20 72 61 69 73 65 20 60 55 73 61 67 65 2e 6e 65   raise `Usage.ne
4130: 77 28 22 23 7b 4e 41 4d 45 7d 3a 20 23 7b 6b 7d  w("#{NAME}: #{k}
4140: 20 69 73 20 6e 6f 74 20 55 54 46 2d 38 20 74 65   is not UTF-8 te
4150: 78 74 20 77 69 74 68 6f 75 74 20 4e 55 4c 22 29  xt without NUL")
4160: 60 20 66 6f 72 20 61 6e 79 20 76 61 6c 75 65 20  ` for any value 
4170: 77 68 65 72 65 20 60 21 76 2e 76 61 6c 69 64 5f  where `!v.valid_
4180: 65 6e 63 6f 64 69 6e 67 3f 20 5c 7c 5c 7c 20 76  encoding? \|\| v
4190: 2e 69 6e 63 6c 75 64 65 73 3f 28 27 5c 30 27 29  .includes?('\0')
41a0: 60 2e 20 46 6f 72 20 74 68 65 20 4a 53 4f 4e 20  `. For the JSON 
41b0: 6f 76 65 72 6c 6f 61 64 2c 20 63 68 65 63 6b 20  overload, check 
41c0: 60 6a 73 6f 6e 2e 76 61 6c 69 64 5f 65 6e 63 6f  `json.valid_enco
41d0: 64 69 6e 67 3f 60 20 61 6e 64 20 72 65 66 75 73  ding?` and refus
41e0: 65 20 61 20 60 5c 75 30 30 30 30 60 20 65 73 63  e a `\u0000` esc
41f0: 61 70 65 2e 20 32 2e 20 49 6e 20 60 73 72 63 2f  ape. 2. In `src/
4200: 6f 63 78 2f 63 67 69 2e 63 72 3a 32 36 60 2c 20  ocx/cgi.cr:26`, 
4210: 6d 6f 76 65 20 60 66 69 65 6c 64 73 20 3d 20 66  move `fields = f
4220: 6f 72 6d 28 72 65 71 75 65 73 74 2c 20 62 6f 64  orm(request, bod
4230: 79 29 60 20 69 6e 73 69 64 65 20 74 68 65 20 60  y)` inside the `
4240: 62 65 67 69 6e 20 e2 80 a6 20 72 65 73 63 75 65  begin … rescue
4250: 20 65 20 3a 20 55 73 61 67 65 60 2e 20 33 2e 20   e : Usage`. 3. 
4260: 49 6e 20 60 73 72 63 2f 6f 63 78 2f 6c 6f 67 2e  In `src/ocx/log.
4270: 63 72 3a 38 32 60 2c 20 75 73 65 20 60 65 2e 6d  cr:82`, use `e.m
4280: 65 73 73 61 67 65 2e 74 72 79 28 26 2e 6c 69 6e  essage.try(&.lin
4290: 65 73 2e 66 69 72 73 74 3f 29 60 2c 20 73 6f 20  es.first?)`, so 
42a0: 6e 6f 20 62 61 63 6b 74 72 61 63 65 20 65 76 65  no backtrace eve
42b0: 72 20 72 65 61 63 68 65 73 20 61 6e 20 61 6e 73  r reaches an ans
42c0: 77 65 72 2e 20 7c 20 60 73 70 65 63 2f 6f 63 78  wer. | `spec/ocx
42d0: 2f 63 6f 6d 6d 61 6e 64 5f 73 70 65 63 2e 63 72  /command_spec.cr
42e0: 60 3a 20 43 47 49 2c 20 43 4c 49 20 61 6e 64 20  `: CGI, CLI and 
42f0: 4d 43 50 20 67 69 76 65 6e 20 60 5c 78 66 66 60  MCP given `\xff`
4300: 20 6f 72 20 60 5c 30 60 20 69 6e 20 61 6e 79 20   or `\0` in any 
4310: 66 69 65 6c 64 20 67 65 74 20 61 20 6f 6e 65 2d  field get a one-
4320: 6c 69 6e 65 20 72 65 61 73 6f 6e 20 28 43 47 49  line reason (CGI
4330: 3a 20 34 30 33 20 77 69 74 68 20 4a 53 4f 4e 29  : 403 with JSON)
4340: 2c 20 61 6e 64 20 6e 6f 6e 65 20 63 72 61 73 68  , and none crash
4350: 2e 20 7c 0a 7c 20 34 20 7c 20 68 69 67 68 20 7c  . |.| 4 | high |
4360: 20 2a 2a 4f 6e 65 20 62 61 64 20 4d 43 50 20 61   **One bad MCP a
4370: 72 67 75 6d 65 6e 74 20 6b 69 6c 6c 73 20 74 68  rgument kills th
4380: 65 20 73 74 64 69 6f 20 73 65 72 76 65 72 2c 20  e stdio server, 
4390: 61 6e 64 20 6f 76 65 72 20 48 54 54 50 20 69 74  and over HTTP it
43a0: 20 61 6e 73 77 65 72 73 20 35 30 30 2e 2a 2a 20   answers 500.** 
43b0: 28 49 6e 70 75 74 20 66 69 6e 64 69 6e 67 20 32  (Input finding 2
43c0: 2e 29 20 7c 20 60 44 2f 74 2f 6d 63 70 31 2e 62  .) | `D/t/mcp1.b
43d0: 69 6e 60 20 68 6f 6c 64 73 20 74 77 6f 20 6c 69  in` holds two li
43e0: 6e 65 73 3a 20 60 6f 63 78 5f 65 64 69 74 20 7b  nes: `ocx_edit {
43f0: 22 70 61 74 68 22 3a 22 52 45 41 44 4d 45 2e 6d  "path":"README.m
4400: 64 22 2c 22 6f 6c 64 22 3a 22 5c 78 66 66 22 2c  d","old":"\xff",
4410: 22 6e 65 77 22 3a 22 78 22 2c 22 64 72 79 5f 72  "new":"x","dry_r
4420: 75 6e 22 3a 74 72 75 65 7d 60 2c 20 74 68 65 6e  un":true}`, then
4430: 20 60 6f 63 78 5f 65 63 68 6f 60 2e 20 52 75 6e   `ocx_echo`. Run
4440: 20 69 6e 20 69 76 79 27 73 20 63 68 65 63 6b 6f   in ivy's checko
4450: 75 74 3a 20 60 63 2e 73 68 20 6f 63 78 32 20 2d  ut: `c.sh ocx2 -
4460: 2d 6d 63 70 20 3c 20 6d 63 70 31 2e 62 69 6e 60  -mcp < mcp1.bin`
4470: 20 65 78 69 74 65 64 20 31 20 77 69 74 68 20 22   exited 1 with "
4480: 55 6e 68 61 6e 64 6c 65 64 20 65 78 63 65 70 74  Unhandled except
4490: 69 6f 6e 3a 20 55 54 46 2d 38 20 65 72 72 6f 72  ion: UTF-8 error
44a0: 3a 20 69 6c 6c 65 67 61 6c 20 62 79 74 65 20 e2  : illegal byte â
44b0: 80 a6 20 69 6e 20 27 4f 43 58 3a 3a 45 64 69 74  €¦ in 'OCX::Edit
44c0: 43 6f 6d 6d 61 6e 64 3a 3a 63 68 61 6e 67 65 64  Command::changed
44d0: 27 22 2c 20 61 6e 64 20 74 68 65 20 65 63 68 6f  '", and the echo
44e0: 20 67 6f 74 20 6e 6f 20 61 6e 73 77 65 72 2e 20   got no answer. 
44f0: 4f 76 65 72 20 48 54 54 50 20 28 60 6f 63 78 32  Over HTTP (`ocx2
4500: 20 2d 2d 6d 63 70 2d 68 74 74 70 20 31 32 37 2e   --mcp-http 127.
4510: 30 2e 30 2e 31 3a 31 38 39 34 35 60 29 2c 20 50  0.0.1:18945`), P
4520: 4f 53 54 20 2f 6d 63 70 20 67 61 76 65 20 2a 2a  OST /mcp gave **
4530: 35 30 30 2a 2a 20 65 61 63 68 20 74 69 6d 65 20  500** each time 
4540: 66 6f 72 3a 20 60 6f 63 78 5f 65 64 69 74 60 20  for: `ocx_edit` 
4550: 6f 6c 64 3d 60 5c 78 66 66 60 3b 20 60 6f 63 78  old=`\xff`; `ocx
4560: 5f 70 6f 73 74 60 20 74 65 78 74 3d 60 5c 78 66  _post` text=`\xf
4570: 66 60 3b 20 60 6f 63 78 5f 65 64 69 74 60 20 6f  f`; `ocx_edit` o
4580: 6c 64 3d 60 22 78 22 2a 32 30 30 30 30 30 60 20  ld=`"x"*200000` 
4590: 28 22 72 65 67 75 6c 61 72 20 65 78 70 72 65 73  ("regular expres
45a0: 73 69 6f 6e 20 69 73 20 74 6f 6f 20 6c 61 72 67  sion is too larg
45b0: 65 22 29 3b 20 60 6f 63 78 5f 73 74 61 67 65 60  e"); `ocx_stage`
45c0: 20 63 68 65 63 6b 6f 75 74 3d 60 22 61 5c 75 30   checkout=`"a\u0
45d0: 30 30 30 62 22 60 20 28 22 53 74 72 69 6e 67 20  000b"` ("String 
45e0: 63 6f 6e 74 61 69 6e 73 20 6e 75 6c 6c 20 62 79  contains null by
45f0: 74 65 22 29 2e 20 54 68 65 20 6e 65 78 74 20 60  te"). The next `
4600: 6f 63 78 5f 65 63 68 6f 60 20 67 61 76 65 20 32  ocx_echo` gave 2
4610: 30 30 2e 20 7c 20 46 69 6e 64 69 6e 67 20 33 27  00. | Finding 3'
4620: 73 20 65 64 67 65 20 63 68 65 63 6b 20 63 6f 76  s edge check cov
4630: 65 72 73 20 74 68 65 20 62 61 64 20 62 79 74 65  ers the bad byte
4640: 73 2e 20 49 6e 20 61 64 64 69 74 69 6f 6e 3a 20  s. In addition: 
4650: 31 2e 20 49 6e 20 60 73 72 63 2f 6f 63 78 2f 63  1. In `src/ocx/c
4660: 6f 6d 6d 61 6e 64 73 2f 65 64 69 74 69 6e 67 2e  ommands/editing.
4670: 63 72 3a 39 35 60 2c 20 72 65 70 6c 61 63 65 20  cr:95`, replace 
4680: 60 74 65 78 74 2e 73 63 61 6e 28 52 65 67 65 78  `text.scan(Regex
4690: 2e 6e 65 77 28 52 65 67 65 78 2e 65 73 63 61 70  .new(Regex.escap
46a0: 65 28 69 6e 70 75 74 2e 6f 6c 64 29 29 29 2e 73  e(input.old))).s
46b0: 69 7a 65 60 20 77 69 74 68 20 60 74 65 78 74 2e  ize` with `text.
46c0: 73 70 6c 69 74 28 69 6e 70 75 74 2e 6f 6c 64 2c  split(input.old,
46d0: 20 33 29 2e 73 69 7a 65 20 2d 20 31 60 2c 20 77   3).size - 1`, w
46e0: 68 69 63 68 20 6e 65 65 64 73 20 6e 6f 20 72 65  hich needs no re
46f0: 67 65 78 2e 20 32 2e 20 49 6e 20 60 73 72 63 2f  gex. 2. In `src/
4700: 6f 63 78 2f 6d 63 70 2e 63 72 60 20 60 4d 63 70  ocx/mcp.cr` `Mcp
4710: 2e 61 6e 73 77 65 72 60 20 61 6e 64 20 60 73 72  .answer` and `sr
4720: 63 2f 6f 63 78 2f 6d 63 70 5f 68 74 74 70 2e 63  c/ocx/mcp_http.c
4730: 72 60 20 60 61 6e 73 77 65 72 60 2c 20 72 65 73  r` `answer`, res
4740: 63 75 65 20 61 6e 79 20 65 78 63 65 70 74 69 6f  cue any exceptio
4750: 6e 20 69 6e 74 6f 20 61 20 4a 53 4f 4e 2d 52 50  n into a JSON-RP
4760: 43 20 65 72 72 6f 72 20 63 61 72 72 79 69 6e 67  C error carrying
4770: 20 69 74 73 20 66 69 72 73 74 20 6c 69 6e 65 2c   its first line,
4780: 20 73 6f 20 74 68 65 20 73 65 72 76 65 72 20 6b   so the server k
4790: 65 65 70 73 20 73 65 72 76 69 6e 67 2e 20 7c 20  eeps serving. | 
47a0: 60 73 70 65 63 2f 6f 63 78 2f 6d 63 70 5f 68 74  `spec/ocx/mcp_ht
47b0: 74 70 5f 73 70 65 63 2e 63 72 60 20 61 6e 64 20  tp_spec.cr` and 
47c0: 61 20 73 74 64 69 6f 20 63 61 73 65 20 69 6e 20  a stdio case in 
47d0: 60 73 70 65 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e  `spec/ocx/comman
47e0: 64 5f 73 70 65 63 2e 63 72 60 3a 20 65 61 63 68  d_spec.cr`: each
47f0: 20 70 61 79 6c 6f 61 64 20 61 62 6f 76 65 20 67   payload above g
4800: 65 74 73 20 61 20 72 65 66 75 73 61 6c 20 6f 72  ets a refusal or
4810: 20 4a 53 4f 4e 2d 52 50 43 20 65 72 72 6f 72 2c   JSON-RPC error,
4820: 20 61 6e 64 20 61 20 66 6f 6c 6c 6f 77 69 6e 67   and a following
4830: 20 63 61 6c 6c 20 69 73 20 61 6e 73 77 65 72 65   call is answere
4840: 64 2e 20 60 63 68 65 63 6b 6f 75 74 5f 74 6f 6f  d. `checkout_too
4850: 6c 73 5f 73 70 65 63 2e 63 72 60 3a 20 60 65 64  ls_spec.cr`: `ed
4860: 69 74 60 20 77 69 74 68 20 6f 6c 64 20 6f 66 20  it` with old of 
4870: 32 30 30 20 30 30 30 20 63 68 61 72 61 63 74 65  200 000 characte
4880: 72 73 20 61 6e 73 77 65 72 73 20 22 6f 6c 64 20  rs answers "old 
4890: 69 73 20 6e 6f 74 20 69 6e 20 e2 80 a6 22 2e 20  is not in …". 
48a0: 7c 0a 7c 20 35 20 7c 20 6d 65 64 69 75 6d 20 7c  |.| 5 | medium |
48b0: 20 2a 2a 45 76 65 72 79 20 70 61 67 65 20 66 6f   **Every page fo
48c0: 72 6d 20 66 6f 72 20 61 20 74 6f 6f 6c 20 6e 65  rm for a tool ne
48d0: 65 64 69 6e 67 20 6e 6f 20 63 61 70 61 62 69 6c  eding no capabil
48e0: 69 74 79 20 73 75 62 6d 69 74 73 20 62 79 20 47  ity submits by G
48f0: 45 54 2e 2a 2a 20 41 73 20 61 20 72 65 73 75 6c  ET.** As a resul
4900: 74 2c 20 63 6f 6c 6c 65 63 74 27 73 20 73 65 63  t, collect's sec
4910: 72 65 74 20 60 63 6f 64 65 60 20 6c 61 6e 64 73  ret `code` lands
4920: 20 69 6e 20 74 68 65 20 55 52 4c 2c 20 61 6e 64   in the URL, and
4930: 20 6c 6f 6e 67 20 71 75 65 72 69 65 73 20 61 72   long queries ar
4940: 65 20 63 75 74 20 6f 66 66 20 77 69 74 68 6f 75  e cut off withou
4950: 74 20 77 61 72 6e 69 6e 67 2e 20 28 50 72 69 76  t warning. (Priv
4960: 61 63 79 20 66 69 6e 64 69 6e 67 20 31 20 61 6e  acy finding 1 an
4970: 64 20 69 6e 70 75 74 20 66 69 6e 64 69 6e 67 20  d input finding 
4980: 37 20 6d 65 72 67 65 64 2e 29 20 7c 20 60 63 75  7 merged.) | `cu
4990: 72 6c 20 2d 73 20 22 24 55 2f 65 78 74 2f 6f 63  rl -s "$U/ext/oc
49a0: 78 32 2d 63 67 69 2f 63 6f 6c 6c 65 63 74 22 60  x2-cgi/collect"`
49b0: 20 73 68 6f 77 73 20 60 3c 66 6f 72 6d 20 6d 65   shows `<form me
49c0: 74 68 6f 64 3d 22 47 45 54 22 20 61 63 74 69 6f  thod="GET" actio
49d0: 6e 3d 22 6f 63 78 32 2d 63 67 69 2f 63 6f 6c 6c  n="ocx2-cgi/coll
49e0: 65 63 74 22 3e 60 20 77 69 74 68 20 60 3c 69 6e  ect">` with `<in
49f0: 70 75 74 20 74 79 70 65 3d 22 70 61 73 73 77 6f  put type="passwo
4a00: 72 64 22 20 6e 61 6d 65 3d 22 63 6f 64 65 22 3e  rd" name="code">
4a10: 60 2e 20 41 66 74 65 72 20 60 72 65 67 69 73 74  `. After `regist
4a20: 65 72 60 20 61 6e 64 20 60 61 70 70 72 6f 76 65  er` and `approve
4a30: 60 20 66 6f 72 20 6c 61 62 2d 37 2c 20 60 63 75  ` for lab-7, `cu
4a40: 72 6c 20 22 24 55 2f 65 78 74 2f 6f 63 78 32 2d  rl "$U/ext/ocx2-
4a50: 63 67 69 2f 63 6f 6c 6c 65 63 74 3f 6c 6f 67 69  cgi/collect?logi
4a60: 6e 3d 6c 61 62 2d 37 26 63 6f 64 65 3d 3c 72 65  n=lab-7&code=<re
4a70: 6d 6f 76 65 64 3e 22 60 20 72 65 74 75 72 6e 65  moved>"` returne
4a80: 64 20 61 20 70 61 67 65 20 73 68 6f 77 69 6e 67  d a page showing
4a90: 20 60 70 61 73 73 77 6f 72 64 20 3a 20 3c 72 65   `password : <re
4aa0: 6d 6f 76 65 64 3e 60 2e 20 54 68 61 74 20 70 61  moved>`. That pa
4ab0: 67 65 20 61 6c 73 6f 20 63 61 72 72 69 65 73 20  ge also carries 
4ac0: 74 68 65 20 53 55 4d 4d 41 52 59 3a 20 22 72 65  the SUMMARY: "re
4ad0: 67 69 73 74 65 72 20 73 65 6e 64 73 20 74 68 65  gister sends the
4ae0: 20 63 6f 64 65 20 69 6e 20 61 20 50 4f 53 54 27   code in a POST'
4af0: 73 20 62 6f 64 79 2c 20 6e 65 76 65 72 20 69 6e  s body, never in
4b00: 20 61 20 55 52 4c 22 2e 20 46 6f 72 20 74 72 75   a URL". For tru
4b10: 6e 63 61 74 69 6f 6e 3a 20 60 72 65 63 65 69 70  ncation: `receip
4b20: 74 3f 63 61 70 61 62 69 6c 69 74 69 65 73 5f 6f  t?capabilities_o
4b30: 66 3d 78 78 78 78 78 78 78 78 78 78 78 78 78 26  f=xxxxxxxxxxxxx&
4b40: 6a 73 6f 6e 3d 6f 6e 26 61 72 74 69 66 61 63 74  json=on&artifact
4b50: 73 3d 3c 34 30 20 53 48 41 33 20 6a 6f 69 6e 65  s=<40 SHA3 joine
4b60: 64 20 62 79 20 2b 3e 60 20 28 32 36 34 37 20 62  d by +>` (2647 b
4b70: 79 74 65 73 29 20 61 6e 73 77 65 72 65 64 20 6f  ytes) answered o
4b80: 6b 3a 74 72 75 65 20 77 69 74 68 20 2a 2a 33 30  k:true with **30
4b90: 2a 2a 20 61 72 74 69 66 61 63 74 73 2e 20 54 68  ** artifacts. Th
4ba0: 65 20 73 61 6d 65 20 71 75 65 72 79 20 61 73 20  e same query as 
4bb0: 61 20 50 4f 53 54 20 67 61 76 65 20 34 30 2e 20  a POST gave 40. 
4bc0: 60 65 63 68 6f 3f 6a 73 6f 6e 3d 6f 6e 26 77 6f  `echo?json=on&wo
4bd0: 72 64 3d 3c 33 30 30 30 20 78 3e 26 66 6c 61 67  rd=<3000 x>&flag
4be0: 3d 6f 6e 60 20 67 61 76 65 20 61 20 77 6f 72 64  =on` gave a word
4bf0: 20 6f 66 20 31 39 36 33 20 63 68 61 72 61 63 74   of 1963 charact
4c00: 65 72 73 20 61 6e 64 20 66 6c 61 67 20 66 61 6c  ers and flag fal
4c10: 73 65 2e 20 57 69 74 68 20 33 31 20 68 61 73 68  se. With 31 hash
4c20: 65 73 20 74 68 65 20 61 6e 73 77 65 72 20 77 61  es the answer wa
4c30: 73 20 61 20 72 65 66 75 73 61 6c 20 6f 6e 20 61  s a refusal on a
4c40: 20 63 75 74 20 68 61 73 68 2c 20 22 62 39 30 35   cut hash, "b905
4c50: 36 22 2e 20 7c 20 49 6e 20 60 73 72 63 2f 6f 63  6". | In `src/oc
4c60: 78 2f 70 61 67 65 2e 63 72 3a 32 33 31 60 2c 20  x/page.cr:231`, 
4c70: 61 6c 77 61 79 73 20 65 6d 69 74 20 60 6d 65 74  always emit `met
4c80: 68 6f 64 3d 22 50 4f 53 54 22 60 2e 20 60 63 67  hod="POST"`. `cg
4c90: 69 2e 63 72 60 20 61 6c 72 65 61 64 79 20 74 61  i.cr` already ta
4ca0: 6b 65 73 20 61 20 50 4f 53 54 20 66 6f 72 20 61  kes a POST for a
4cb0: 20 74 6f 6f 6c 20 77 69 74 68 20 6e 6f 20 4e 45   tool with no NE
4cc0: 45 44 53 20 77 69 74 68 6f 75 74 20 61 20 73 61  EDS without a sa
4cd0: 6d 65 2d 73 69 74 65 20 63 68 65 63 6b 3a 20 63  me-site check: c
4ce0: 6f 6c 6c 65 63 74 20 61 6e 64 20 72 65 63 65 69  ollect and recei
4cf0: 70 74 20 62 6f 74 68 20 61 6e 73 77 65 72 65 64  pt both answered
4d00: 20 6f 6b 20 62 79 20 50 4f 53 54 20 68 65 72 65   ok by POST here
4d10: 2e 20 7c 20 41 20 70 61 67 65 20 73 70 65 63 20  . | A page spec 
4d20: 28 60 73 70 65 63 2f 6f 63 78 2f 73 74 79 6c 65  (`spec/ocx/style
4d30: 73 5f 73 70 65 63 2e 63 72 60 20 6f 72 20 60 63  s_spec.cr` or `c
4d40: 6f 6d 6d 61 6e 64 5f 73 70 65 63 2e 63 72 60 29  ommand_spec.cr`)
4d50: 20 74 68 61 74 20 63 68 65 63 6b 73 20 65 76 65   that checks eve
4d60: 72 79 20 60 3c 66 6f 72 6d 3e 60 20 69 73 20 50  ry `<form>` is P
4d70: 4f 53 54 2e 20 41 20 72 65 63 65 69 70 74 20 61  OST. A receipt a
4d80: 73 6b 65 64 20 6f 66 20 34 30 20 68 61 73 68 65  sked of 40 hashe
4d90: 73 20 74 68 72 6f 75 67 68 20 74 68 65 20 66 6f  s through the fo
4da0: 72 6d 27 73 20 6d 65 74 68 6f 64 20 72 65 74 75  rm's method retu
4db0: 72 6e 73 20 34 30 2e 20 7c 0a 7c 20 36 20 7c 20  rns 40. |.| 6 | 
4dc0: 6d 65 64 69 75 6d 20 7c 20 2a 2a 41 20 63 6c 6f  medium | **A clo
4dd0: 6e 65 20 77 72 69 74 65 20 77 68 6f 73 65 20 70  ne write whose p
4de0: 75 73 68 20 6d 65 65 74 73 20 61 6e 20 6f 75 74  ush meets an out
4df0: 73 69 64 65 20 6c 6f 63 6b 20 69 73 20 72 65 70  side lock is rep
4e00: 6f 72 74 65 64 20 61 73 20 66 61 69 6c 65 64 20  orted as failed 
4e10: 77 69 74 68 20 6e 6f 20 68 61 73 68 2c 20 79 65  with no hash, ye
4e20: 74 20 74 68 65 20 6e 65 78 74 20 73 79 6e 63 20  t the next sync 
4e30: 73 65 6e 64 73 20 69 74 2e 2a 2a 20 28 43 6f 6e  sends it.** (Con
4e40: 63 75 72 72 65 6e 63 79 20 66 69 6e 64 69 6e 67  currency finding
4e50: 20 33 2e 29 20 7c 20 60 74 41 2e 73 68 20 70 75   3.) | `tA.sh pu
4e60: 73 68 20 63 36 62 35 66 30 35 63 20 22 72 65 70  sh c6b5f05c "rep
4e70: 6c 79 20 45 20 68 65 6c 64 20 62 65 66 6f 72 65  ly E held before
4e80: 20 70 75 73 68 22 60 20 61 6e 73 77 65 72 65 64   push"` answered
4e90: 20 6f 6b 3a 66 61 6c 73 65 3a 20 22 66 6f 73 73   ok:false: "foss
4ea0: 69 6c 20 70 75 73 68 20 6f 6e 20 e2 80 a6 63 6c  il push on …cl
4eb0: 6f 6e 65 2e 66 6f 73 73 69 6c 3a 20 61 20 77 72  one.fossil: a wr
4ec0: 69 74 65 72 20 6f 75 74 73 69 64 65 20 4f 43 58  iter outside OCX
4ed0: 20 68 65 6c 64 20 e2 80 a6 20 44 61 74 61 62 61   held … Databa
4ee0: 73 65 20 65 72 72 6f 72 3a 20 64 61 74 61 62 61  se error: databa
4ef0: 73 65 20 69 73 20 6c 6f 63 6b 65 64 3a 20 7b 44  se is locked: {D
4f00: 45 4c 45 54 45 20 46 52 4f 4d 20 75 6e e2 80 a6  ELETE FROM un…
4f10: 22 2e 20 54 68 65 20 63 6c 6f 6e 65 20 6b 65 70  ". The clone kep
4f20: 74 20 35 64 35 61 66 33 65 37 2e 20 60 74 41 2e  t 5d5af3e7. `tA.
4f30: 73 68 20 70 75 73 68 20 34 31 62 31 39 66 38 37  sh push 41b19f87
4f40: 20 22 74 69 63 6b 65 74 20 63 6f 6d 6d 65 6e 74   "ticket comment
4f50: 20 4c e2 80 a6 22 60 20 61 6e 73 77 65 72 65 64   L…"` answered
4f60: 20 6f 6b 3a 66 61 6c 73 65 2c 20 61 6e 64 20 74   ok:false, and t
4f70: 68 65 20 63 6c 6f 6e 65 20 6b 65 70 74 20 37 35  he clone kept 75
4f80: 63 35 31 31 35 33 20 28 75 6e 73 65 6e 74 20 31  c51153 (unsent 1
4f90: 29 2e 20 54 68 65 20 73 65 72 76 65 72 20 68 61  ). The server ha
4fa0: 64 20 6e 65 69 74 68 65 72 2e 20 41 66 74 65 72  d neither. After
4fb0: 20 74 68 65 20 6e 65 78 74 20 60 6f 63 78 32 20   the next `ocx2 
4fc0: 70 6f 73 74 20 63 36 62 35 66 30 35 63 20 22 61  post c6b5f05c "a
4fd0: 20 6c 61 74 65 72 20 70 6f 73 74 22 60 20 28 6f   later post"` (o
4fe0: 6b 29 2c 20 74 68 65 20 73 65 72 76 65 72 20 68  k), the server h
4ff0: 6f 6c 64 73 20 37 35 63 35 31 31 35 33 20 28 72  olds 75c51153 (r
5000: 69 64 20 32 31 29 20 61 6e 64 20 35 64 35 61 66  id 21) and 5d5af
5010: 33 65 37 20 28 72 69 64 20 32 33 29 2c 20 62 6f  3e7 (rid 23), bo
5020: 74 68 20 72 65 63 65 69 76 65 64 20 66 72 6f 6d  th received from
5030: 20 69 76 79 2e 20 7c 20 49 6e 20 60 73 72 63 2f   ivy. | In `src/
5040: 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f 70 6f 73  ocx/commands/pos
5050: 74 2e 63 72 3a 33 30 60 20 61 6e 64 20 60 73 72  t.cr:30` and `sr
5060: 63 2f 6f 63 78 2f 77 72 69 74 65 73 2e 63 72 3a  c/ocx/writes.cr:
5070: 33 33 60 2c 20 72 65 73 63 75 65 20 60 46 6f 73  33`, rescue `Fos
5080: 73 69 6c 3a 3a 46 61 69 6c 65 64 60 20 66 72 6f  sil::Failed` fro
5090: 6d 20 60 63 6c 6f 6e 65 2e 70 75 73 68 60 2e 20  m `clone.push`. 
50a0: 52 61 69 73 65 20 74 68 65 20 65 78 69 73 74 69  Raise the existi
50b0: 6e 67 20 22 69 73 20 69 6e 20 74 68 65 20 63 6c  ng "is in the cl
50c0: 6f 6e 65 2c 20 62 75 74 20 69 74 73 20 70 75 73  one, but its pus
50d0: 68 20 64 69 64 20 6e 6f 74 20 72 65 61 63 68 20  h did not reach 
50e0: 74 68 65 20 73 65 72 76 65 64 20 72 65 70 6f 73  the served repos
50f0: 69 74 6f 72 79 20 28 e2 80 a6 29 3b 20 61 20 6c  itory (…); a l
5100: 61 74 65 72 20 73 79 6e 63 20 73 65 6e 64 73 20  ater sync sends 
5110: 69 74 22 20 6d 65 73 73 61 67 65 2c 20 61 6e 64  it" message, and
5120: 20 6e 61 6d 65 20 60 68 61 73 68 60 20 6f 72 20   name `hash` or 
5130: 60 63 68 61 6e 67 65 60 20 69 6e 20 69 74 2e 20  `change` in it. 
5140: 7c 20 60 73 70 65 63 2f 6f 63 78 2f 70 6f 73 74  | `spec/ocx/post
5150: 5f 73 70 65 63 2e 63 72 60 3a 20 77 69 74 68 20  _spec.cr`: with 
5160: 74 68 65 20 70 75 73 68 20 66 61 69 6c 69 6e 67  the push failing
5170: 20 77 69 74 68 20 22 64 61 74 61 62 61 73 65 20   with "database 
5180: 69 73 20 6c 6f 63 6b 65 64 22 2c 20 74 68 65 20  is locked", the 
5190: 72 65 66 75 73 61 6c 20 6e 61 6d 65 73 20 74 68  refusal names th
51a0: 65 20 77 72 69 74 74 65 6e 20 68 61 73 68 20 61  e written hash a
51b0: 6e 64 20 73 61 79 73 20 61 20 6c 61 74 65 72 20  nd says a later 
51c0: 73 79 6e 63 20 73 65 6e 64 73 20 69 74 2e 20 7c  sync sends it. |
51d0: 0a 7c 20 37 20 7c 20 6d 65 64 69 75 6d 20 7c 20  .| 7 | medium | 
51e0: 2a 2a 46 72 6f 6d 20 61 20 63 6c 6f 6e 65 2c 20  **From a clone, 
51f0: 74 68 65 20 73 65 72 76 65 72 27 73 20 72 65 61  the server's rea
5200: 73 6f 6e 20 66 6f 72 20 61 20 72 65 66 75 73 61  son for a refusa
5210: 6c 20 69 73 20 6c 6f 73 74 3a 20 22 74 68 65 20  l is lost: "the 
5220: 73 65 72 76 65 72 20 61 6e 73 77 65 72 65 64 20  server answered 
5230: 34 30 33 22 2e 2a 2a 20 28 49 6e 70 75 74 20 66  403".** (Input f
5240: 69 6e 64 69 6e 67 20 35 2e 29 20 7c 20 49 6e 20  inding 5.) | In 
5250: 69 76 79 27 73 20 63 68 65 63 6b 6f 75 74 2c 20  ivy's checkout, 
5260: 60 63 2e 73 68 20 6f 63 78 32 20 2d 2d 6a 73 6f  `c.sh ocx2 --jso
5270: 6e 20 72 65 63 65 69 70 74 20 2d 2d 61 72 74 69  n receipt --arti
5280: 66 61 63 74 73 20 27 61 20 62 27 60 20 67 61 76  facts 'a b'` gav
5290: 65 20 73 74 6f 70 70 65 64 20 22 74 68 65 20 73  e stopped "the s
52a0: 65 72 76 65 72 20 61 6e 73 77 65 72 65 64 20 34  erver answered 4
52b0: 30 33 22 2c 20 77 69 74 68 20 6c 6f 67 20 60 5b  03", with log `[
52c0: 72 65 61 64 5f 72 65 6d 6f 74 65 2c 20 61 73 6b  read_remote, ask
52d0: 5f 73 65 72 76 65 72 5f 72 65 63 65 69 70 74 73  _server_receipts
52e0: 5d 60 2e 20 53 65 6e 74 20 73 74 72 61 69 67 68  ]`. Sent straigh
52f0: 74 20 74 6f 20 74 68 65 20 73 65 72 76 65 72 2c  t to the server,
5300: 20 74 68 65 20 73 61 6d 65 20 50 4f 53 54 20 68   the same POST h
5310: 61 73 20 74 68 65 20 62 6f 64 79 20 60 22 73 74  as the body `"st
5320: 6f 70 70 65 64 22 3a 22 72 65 63 65 69 70 74 3a  opped":"receipt:
5330: 20 5c 22 61 5c 22 20 69 73 20 6e 6f 74 20 61 6e   \"a\" is not an
5340: 20 61 72 74 69 66 61 63 74 27 73 20 68 61 73 68   artifact's hash
5350: 20 69 6e 20 66 75 6c 6c 22 60 2e 20 7c 20 49 6e   in full"`. | In
5360: 20 60 73 72 63 2f 6f 63 78 2f 73 65 72 76 65 72   `src/ocx/server
5370: 2e 63 72 3a 31 38 36 60 2c 20 6d 61 6b 65 20 74  .cr:186`, make t
5380: 68 65 20 67 75 61 72 64 20 60 75 6e 6c 65 73 73  he guard `unless
5390: 20 72 65 73 70 6f 6e 73 65 2e 73 75 63 63 65 73   response.succes
53a0: 73 3f 20 5c 7c 5c 7c 20 72 65 73 70 6f 6e 73 65  s? \|\| response
53b0: 2e 73 74 61 74 75 73 5f 63 6f 64 65 20 3d 3d 20  .status_code == 
53c0: 34 30 33 60 2c 20 73 6f 20 74 68 65 20 34 30 33  403`, so the 403
53d0: 20 62 6f 64 79 20 69 73 20 72 65 61 64 20 61 73   body is read as
53e0: 20 74 68 65 20 41 6e 73 77 65 72 2e 20 49 6e 20   the Answer. In 
53f0: 60 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64  `src/ocx/command
5400: 73 2f 72 65 63 65 69 70 74 2e 63 72 3a 37 34 60  s/receipt.cr:74`
5410: 2c 20 77 72 69 74 65 20 60 23 7b 61 6e 73 77 65  , write `#{answe
5420: 72 2e 73 74 6f 70 70 65 64 20 5c 7c 5c 7c 20 22  r.stopped \|\| "
5430: 69 74 20 67 61 76 65 20 6e 6f 20 72 65 61 73 6f  it gave no reaso
5440: 6e 22 7d 60 2e 20 7c 20 60 73 70 65 63 2f 6f 63  n"}`. | `spec/oc
5450: 78 2f 72 65 63 65 69 70 74 5f 73 70 65 63 2e 63  x/receipt_spec.c
5460: 72 60 3a 20 66 72 6f 6d 20 61 20 63 6c 6f 6e 65  r`: from a clone
5470: 2c 20 61 20 62 61 64 20 68 61 73 68 27 73 20 72  , a bad hash's r
5480: 65 66 75 73 61 6c 20 63 61 72 72 69 65 73 20 74  efusal carries t
5490: 68 65 20 73 65 72 76 65 72 27 73 20 22 69 73 20  he server's "is 
54a0: 6e 6f 74 20 61 6e 20 61 72 74 69 66 61 63 74 27  not an artifact'
54b0: 73 20 68 61 73 68 20 69 6e 20 66 75 6c 6c 22 2e  s hash in full".
54c0: 20 7c 0a 7c 20 38 20 7c 20 6d 65 64 69 75 6d 20   |.| 8 | medium 
54d0: 7c 20 2a 2a 41 20 72 65 6d 6f 74 65 20 74 68 61  | **A remote tha
54e0: 74 20 74 72 69 63 6b 6c 65 73 20 62 79 74 65 73  t trickles bytes
54f0: 20 73 74 61 6c 6c 73 20 63 6c 6f 6e 65 20 61 73   stalls clone as
5500: 6b 73 20 77 69 74 68 20 6e 6f 20 6c 69 6d 69 74  ks with no limit
5510: 2c 20 69 6e 63 6c 75 64 69 6e 67 20 4d 43 50 20  , including MCP 
5520: 73 74 61 72 74 75 70 20 69 6e 20 61 20 63 6c 6f  startup in a clo
5530: 6e 65 2e 2a 2a 20 28 49 6e 70 75 74 20 66 69 6e  ne.** (Input fin
5540: 64 69 6e 67 20 36 2e 29 20 7c 20 60 44 2f 74 2f  ding 6.) | `D/t/
5550: 74 72 69 63 6b 6c 65 2e 70 79 20 31 38 39 34 36  trickle.py 18946
5560: 20 74 72 69 63 6b 6c 65 60 20 73 65 6e 64 73 20   trickle` sends 
5570: 68 65 61 64 65 72 73 20 77 69 74 68 20 43 6f 6e  headers with Con
5580: 74 65 6e 74 2d 4c 65 6e 67 74 68 20 31 30 30 2c  tent-Length 100,
5590: 20 74 68 65 6e 20 6f 6e 65 20 62 79 74 65 20 65   then one byte e
55a0: 76 65 72 79 20 34 20 73 2e 20 41 20 63 6f 70 79  very 4 s. A copy
55b0: 20 6f 66 20 69 76 79 27 73 20 63 6c 6f 6e 65 20   of ivy's clone 
55c0: 61 74 20 60 44 2f 74 2f 74 72 69 63 6b 2f 74 72  at `D/t/trick/tr
55d0: 65 65 60 20 68 61 73 20 69 74 73 20 72 65 6d 6f  ee` has its remo
55e0: 74 65 20 73 65 74 20 74 6f 20 60 68 74 74 70 3a  te set to `http:
55f0: 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a 31 38 39 34  //127.0.0.1:1894
5600: 36 2f 60 20 61 6e 64 20 69 74 73 20 64 65 66 61  6/` and its defa
5610: 75 6c 74 20 75 73 65 72 20 73 65 74 20 74 6f 20  ult user set to 
5620: 69 76 79 2e 20 60 74 69 6d 65 6f 75 74 20 34 35  ivy. `timeout 45
5630: 20 63 2e 73 68 20 6f 63 78 32 20 2d 2d 6a 73 6f   c.sh ocx2 --jso
5640: 6e 20 72 65 63 65 69 70 74 20 2d 2d 61 72 74 69  n receipt --arti
5650: 66 61 63 74 73 20 39 30 61 66 31 39 39 37 e2 80  facts 90af1997â€
5660: a6 60 20 77 61 73 20 6b 69 6c 6c 65 64 20 61 74  ¦` was killed at
5670: 20 2a 2a 34 35 2e 30 30 20 73 2a 2a 20 77 69 74   **45.00 s** wit
5680: 68 20 6e 6f 20 61 6e 73 77 65 72 2e 20 60 6f 63  h no answer. `oc
5690: 78 32 20 2d 2d 6d 63 70 20 3c 20 69 6e 69 74 2e  x2 --mcp < init.
56a0: 6a 73 6f 6e 60 2c 20 77 68 65 72 65 20 69 6e 69  json`, where ini
56b0: 74 2e 6a 73 6f 6e 20 69 73 20 61 6e 20 60 69 6e  t.json is an `in
56c0: 69 74 69 61 6c 69 7a 65 60 20 6d 65 73 73 61 67  itialize` messag
56d0: 65 2c 20 77 61 73 20 6b 69 6c 6c 65 64 20 61 74  e, was killed at
56e0: 20 2a 2a 33 30 20 73 2a 2a 20 77 69 74 68 20 6e   **30 s** with n
56f0: 6f 20 61 6e 73 77 65 72 20 28 65 78 69 74 20 31  o answer (exit 1
5700: 34 33 29 2e 20 41 67 61 69 6e 73 74 20 6e 6f 74  43). Against not
5710: 68 69 6e 67 20 6c 69 73 74 65 6e 69 6e 67 2c 20  hing listening, 
5720: 74 68 65 20 72 65 66 75 73 61 6c 20 63 6f 6d 65  the refusal come
5730: 73 20 69 6e 20 30 2e 30 33 20 73 2e 20 7c 20 49  s in 0.03 s. | I
5740: 6e 20 60 73 72 63 2f 6f 63 78 2f 73 65 72 76 65  n `src/ocx/serve
5750: 72 2e 63 72 3a 31 38 37 60 2c 20 72 65 70 6c 61  r.cr:187`, repla
5760: 63 65 20 60 49 4f 2e 63 6f 70 79 28 72 65 73 70  ce `IO.copy(resp
5770: 6f 6e 73 65 2e 62 6f 64 79 5f 69 6f 2c 20 73 2c  onse.body_io, s,
5780: 20 42 59 54 45 53 29 60 20 77 69 74 68 20 61 20   BYTES)` with a 
5790: 63 68 75 6e 6b 65 64 20 63 6f 70 79 20 74 68 61  chunked copy tha
57a0: 74 20 72 61 69 73 65 73 20 60 52 65 66 75 73 65  t raises `Refuse
57b0: 64 2e 6e 65 77 28 22 74 68 65 20 73 65 72 76 65  d.new("the serve
57c0: 72 20 64 69 64 20 6e 6f 74 20 61 6e 73 77 65 72  r did not answer
57d0: 20 77 69 74 68 69 6e 20 23 7b 57 49 54 48 49 4e   within #{WITHIN
57e0: 7d 22 29 60 20 6f 6e 63 65 20 60 54 69 6d 65 2e  }")` once `Time.
57f0: 6d 6f 6e 6f 74 6f 6e 69 63 60 20 70 61 73 73 65  monotonic` passe
5800: 73 20 61 20 64 65 61 64 6c 69 6e 65 20 73 65 74  s a deadline set
5810: 20 61 74 20 74 68 65 20 72 65 71 75 65 73 74 27   at the request'
5820: 73 20 73 74 61 72 74 2e 20 54 68 65 6e 20 57 49  s start. Then WI
5830: 54 48 49 4e 20 62 6f 75 6e 64 73 20 74 68 65 20  THIN bounds the 
5840: 77 68 6f 6c 65 20 62 6f 64 79 2c 20 6e 6f 74 20  whole body, not 
5850: 65 61 63 68 20 72 65 61 64 2e 20 7c 20 60 73 70  each read. | `sp
5860: 65 63 2f 6f 63 78 2f 72 65 63 65 69 70 74 5f 73  ec/ocx/receipt_s
5870: 70 65 63 2e 63 72 60 20 61 6e 64 20 60 72 65 6d  pec.cr` and `rem
5880: 6f 74 65 5f 6e 6f 64 65 5f 73 70 65 63 2e 63 72  ote_node_spec.cr
5890: 60 2c 20 77 69 74 68 20 61 20 74 72 69 63 6b 6c  `, with a trickl
58a0: 69 6e 67 20 73 74 61 6e 64 2d 69 6e 3a 20 72 65  ing stand-in: re
58b0: 66 75 73 65 64 20 77 69 74 68 69 6e 20 61 62 6f  fused within abo
58c0: 75 74 20 32 c3 97 57 49 54 48 49 4e 2e 20 4d 43  ut 2×WITHIN. MC
58d0: 50 20 60 69 6e 69 74 69 61 6c 69 7a 65 60 20 69  P `initialize` i
58e0: 6e 20 73 75 63 68 20 61 20 63 6c 6f 6e 65 20 61  n such a clone a
58f0: 6e 73 77 65 72 73 20 77 69 74 68 69 6e 20 74 68  nswers within th
5900: 65 20 73 61 6d 65 20 62 6f 75 6e 64 2e 20 7c 0a  e same bound. |.
5910: 7c 20 39 20 7c 20 6c 6f 77 20 7c 20 2a 2a 72 65  | 9 | low | **re
5920: 63 65 69 70 74 20 6f 66 20 61 62 6f 75 74 20 32  ceipt of about 2
5930: 30 30 30 20 6f 72 20 6d 6f 72 65 20 61 72 74 69  000 or more arti
5940: 66 61 63 74 73 20 69 73 20 72 65 66 75 73 65 64  facts is refused
5950: 20 77 69 74 68 20 61 6e 20 69 6e 74 65 72 6e 61   with an interna
5960: 6c 20 45 32 42 49 47 20 6d 65 73 73 61 67 65 2e  l E2BIG message.
5970: 2a 2a 20 28 49 6e 70 75 74 20 66 69 6e 64 69 6e  ** (Input findin
5980: 67 20 38 2e 29 20 7c 20 41 20 50 4f 53 54 20 6f  g 8.) | A POST o
5990: 66 20 60 6a 73 6f 6e 3d 6f 6e 26 61 72 74 69 66  f `json=on&artif
59a0: 61 63 74 73 3d 3c 4e 20 68 61 73 68 65 73 3e 60  acts=<N hashes>`
59b0: 20 74 6f 20 60 24 55 2f 65 78 74 2f 6f 63 78 32   to `$U/ext/ocx2
59c0: 2d 63 67 69 2f 72 65 63 65 69 70 74 60 3a 20 4e  -cgi/receipt`: N
59d0: 3d 31 39 30 30 20 28 31 32 33 20 35 31 37 20 62  =1900 (123 517 b
59e0: 79 74 65 73 29 20 67 61 76 65 20 32 30 30 20 77  ytes) gave 200 w
59f0: 69 74 68 20 31 39 30 30 20 61 6e 73 77 65 72 73  ith 1900 answers
5a00: 2e 20 4e 3d 32 30 30 30 20 28 31 33 30 20 30 31  . N=2000 (130 01
5a10: 37 20 62 79 74 65 73 29 20 67 61 76 65 20 34 30  7 bytes) gave 40
5a20: 33 2c 20 22 72 65 61 64 5f 72 65 63 65 69 70 74  3, "read_receipt
5a30: 73 20 66 61 69 6c 65 64 3a 20 45 72 72 6f 72 20  s failed: Error 
5a40: 65 78 65 63 75 74 69 6e 67 20 70 72 6f 63 65 73  executing proces
5a50: 73 3a 20 27 66 6f 73 73 69 6c 27 3a 20 41 72 67  s: 'fossil': Arg
5a60: 75 6d 65 6e 74 20 6c 69 73 74 20 74 6f 6f 20 6c  ument list too l
5a70: 6f 6e 67 22 2e 20 60 63 61 70 61 62 69 6c 69 74  ong". `capabilit
5a80: 69 65 73 5f 6f 66 3d 3c 32 30 30 30 30 30 20 78  ies_of=<200000 x
5a90: 3e 60 20 67 69 76 65 73 20 74 68 65 20 73 61 6d  >` gives the sam
5aa0: 65 20 6d 65 73 73 61 67 65 2e 20 7c 20 49 6e 20  e message. | In 
5ab0: 60 73 72 63 2f 6f 63 78 2f 66 6f 73 73 69 6c 2f  `src/ocx/fossil/
5ac0: 73 61 69 64 2e 63 72 3a 31 34 36 60 20 60 72 65  said.cr:146` `re
5ad0: 63 65 69 70 74 73 60 2c 20 75 73 65 20 60 68 61  ceipts`, use `ha
5ae0: 73 68 65 73 2e 65 61 63 68 5f 73 6c 69 63 65 28  shes.each_slice(
5af0: 35 30 30 29 2e 66 6c 61 74 5f 6d 61 70 20 7b 20  500).flat_map { 
5b00: e2 80 a6 20 7d 60 20 77 69 74 68 20 6f 6e 65 20  … }` with one 
5b10: 71 75 65 72 79 20 70 65 72 20 73 6c 69 63 65 2e  query per slice.
5b20: 20 49 6e 20 60 52 65 63 65 69 70 74 43 6f 6d 6d   In `ReceiptComm
5b30: 61 6e 64 60 2c 20 72 65 66 75 73 65 20 61 20 60  and`, refuse a `
5b40: 63 61 70 61 62 69 6c 69 74 69 65 73 5f 6f 66 60  capabilities_of`
5b50: 20 6c 6f 6e 67 65 72 20 74 68 61 6e 20 61 20 46   longer than a F
5b60: 6f 73 73 69 6c 20 6c 6f 67 69 6e 20 63 61 6e 20  ossil login can 
5b70: 62 65 2c 20 77 68 69 63 68 20 69 73 20 61 20 6f  be, which is a o
5b80: 6e 65 2d 6c 69 6e 65 20 55 73 61 67 65 2e 20 7c  ne-line Usage. |
5b90: 20 60 73 70 65 63 2f 6f 63 78 2f 72 65 63 65 69   `spec/ocx/recei
5ba0: 70 74 5f 73 70 65 63 2e 63 72 60 3a 20 35 30 30  pt_spec.cr`: 500
5bb0: 30 20 68 61 73 68 65 73 20 61 6e 73 77 65 72 20  0 hashes answer 
5bc0: 35 30 30 30 2e 20 41 20 32 30 30 20 30 30 30 2d  5000. A 200 000-
5bd0: 63 68 61 72 61 63 74 65 72 20 75 73 65 72 20 69  character user i
5be0: 73 20 72 65 66 75 73 65 64 20 77 69 74 68 20 61  s refused with a
5bf0: 20 6f 6e 65 2d 6c 69 6e 65 20 72 65 61 73 6f 6e   one-line reason
5c00: 2e 20 7c 0a 7c 20 31 30 20 7c 20 6c 6f 77 20 7c  . |.| 10 | low |
5c10: 20 2a 2a 41 20 63 6c 6f 6e 65 20 70 61 73 73 65   **A clone passe
5c20: 73 20 74 68 65 20 73 65 72 76 65 72 27 73 20 72  s the server's r
5c30: 65 63 65 69 70 74 20 61 6e 73 77 65 72 20 74 68  eceipt answer th
5c40: 72 6f 75 67 68 20 75 6e 63 68 65 63 6b 65 64 2e  rough unchecked.
5c50: 2a 2a 20 28 49 6e 70 75 74 20 66 69 6e 64 69 6e  ** (Input findin
5c60: 67 20 39 2e 29 20 7c 20 54 68 65 20 73 74 61 6e  g 9.) | The stan
5c70: 64 2d 69 6e 20 28 60 74 72 69 63 6b 6c 65 2e 70  d-in (`trickle.p
5c80: 79 20 31 38 39 34 36 20 61 6e 73 77 65 72 20 44  y 18946 answer D
5c90: 2f 74 2f 66 6f 72 67 65 64 2e 6a 73 6f 6e 60 29  /t/forged.json`)
5ca0: 20 61 6e 73 77 65 72 73 20 61 72 74 69 66 61 63   answers artifac
5cb0: 74 20 60 22 7a 7a 22 60 20 61 6e 64 20 75 73 65  t `"zz"` and use
5cc0: 72 20 69 76 79 20 77 69 74 68 20 63 61 70 61 62  r ivy with capab
5cd0: 69 6c 69 74 69 65 73 20 60 73 60 2e 20 60 63 2e  ilities `s`. `c.
5ce0: 73 68 20 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 72  sh ocx2 --json r
5cf0: 65 63 65 69 70 74 20 2d 2d 61 72 74 69 66 61 63  eceipt --artifac
5d00: 74 73 20 39 30 61 66 31 39 39 37 e2 80 a6 20 2d  ts 90af1997… -
5d10: 2d 63 61 70 61 62 69 6c 69 74 69 65 73 2d 6f 66  -capabilities-of
5d20: 20 69 76 79 60 20 65 78 69 74 65 64 20 72 63 20   ivy` exited rc 
5d30: 30 2c 20 6f 6b 3a 74 72 75 65 2c 20 77 69 74 68  0, ok:true, with
5d40: 20 60 22 61 72 74 69 66 61 63 74 22 3a 22 7a 7a   `"artifact":"zz
5d50: 22 60 2e 20 54 68 65 20 68 61 73 68 20 74 68 61  "`. The hash tha
5d60: 74 20 77 61 73 20 61 73 6b 65 64 20 64 6f 65 73  t was asked does
5d70: 20 6e 6f 74 20 61 70 70 65 61 72 2e 20 7c 20 49   not appear. | I
5d80: 6e 20 60 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61  n `src/ocx/comma
5d90: 6e 64 73 2f 72 65 63 65 69 70 74 2e 63 72 3a 31  nds/receipt.cr:1
5da0: 37 35 60 20 60 61 73 6b 65 64 60 2c 20 72 65 66  75` `asked`, ref
5db0: 75 73 65 20 22 74 68 65 20 73 65 72 76 65 72 27  use "the server'
5dc0: 73 20 61 6e 73 77 65 72 20 64 6f 65 73 20 6e 6f  s answer does no
5dd0: 74 20 63 6f 76 65 72 20 77 68 61 74 20 77 61 73  t cover what was
5de0: 20 61 73 6b 65 64 22 20 75 6e 6c 65 73 73 20 60   asked" unless `
5df0: 73 65 72 76 65 72 2e 61 72 74 69 66 61 63 74 73  server.artifacts
5e00: 2e 6d 61 70 28 26 2e 61 72 74 69 66 61 63 74 29  .map(&.artifact)
5e10: 60 20 65 71 75 61 6c 73 20 74 68 65 20 61 73 6b  ` equals the ask
5e20: 65 64 20 68 61 73 68 65 73 20 69 6e 20 6f 72 64  ed hashes in ord
5e30: 65 72 2c 20 61 6e 64 20 60 73 65 72 76 65 72 2e  er, and `server.
5e40: 75 73 65 72 2e 74 72 79 28 26 2e 75 73 65 72 29  user.try(&.user)
5e50: 60 20 65 71 75 61 6c 73 20 60 63 61 70 61 62 69  ` equals `capabi
5e60: 6c 69 74 69 65 73 5f 6f 66 60 2e 20 41 70 70 6c  lities_of`. Appl
5e70: 79 20 74 68 65 20 73 61 6d 65 20 75 73 65 72 20  y the same user 
5e80: 63 68 65 63 6b 20 69 6e 20 60 73 65 72 76 65 72  check in `server
5e90: 2e 63 72 3a 31 35 30 60 20 60 63 61 70 61 62 69  .cr:150` `capabi
5ea0: 6c 69 74 69 65 73 5f 61 74 60 2e 20 7c 20 60 73  lities_at`. | `s
5eb0: 70 65 63 2f 6f 63 78 2f 72 65 63 65 69 70 74 5f  pec/ocx/receipt_
5ec0: 73 70 65 63 2e 63 72 60 20 77 69 74 68 20 61 20  spec.cr` with a 
5ed0: 73 74 61 6e 64 2d 69 6e 20 67 69 76 69 6e 67 20  stand-in giving 
5ee0: 61 20 66 6f 72 65 69 67 6e 20 68 61 73 68 20 6f  a foreign hash o
5ef0: 72 20 75 73 65 72 3a 20 72 65 66 75 73 65 64 2c  r user: refused,
5f00: 20 6e 61 6d 69 6e 67 20 74 68 65 20 73 65 72 76   naming the serv
5f10: 65 72 2e 20 7c 0a 7c 20 31 31 20 7c 20 6c 6f 77  er. |.| 11 | low
5f20: 20 7c 20 2a 2a 4f 43 58 27 73 20 74 75 72 6e 20   | **OCX's turn 
5f30: 69 73 20 68 65 6c 64 20 74 68 72 6f 75 67 68 20  is held through 
5f40: 46 6f 73 73 69 6c 27 73 20 31 35 20 73 20 62 75  Fossil's 15 s bu
5f50: 73 79 20 77 61 69 74 2e 2a 2a 20 55 6e 64 65 72  sy wait.** Under
5f60: 20 61 6e 20 6f 75 74 73 69 64 65 20 6c 6f 63 6b   an outside lock
5f70: 2c 20 4e 20 77 65 62 20 77 72 69 74 65 73 20 61  , N web writes a
5f80: 6e 73 77 65 72 20 61 74 20 31 35 2c 20 33 30 20  nswer at 15, 30 
5f90: 61 6e 64 20 34 35 20 73 2e 20 28 43 6f 6e 63 75  and 45 s. (Concu
5fa0: 72 72 65 6e 63 79 20 66 69 6e 64 69 6e 67 20 36  rrency finding 6
5fb0: 2e 29 20 7c 20 60 74 4d 2e 73 68 60 20 68 6f 6c  .) | `tM.sh` hol
5fc0: 64 73 20 60 72 65 70 6f 2e 66 6f 73 73 69 6c 60  ds `repo.fossil`
5fd0: 2c 20 74 68 65 6e 20 74 68 72 65 65 20 70 61 72  , then three par
5fe0: 61 6c 6c 65 6c 20 60 63 75 72 6c 20 2d 62 20 6a  allel `curl -b j
5ff0: 61 72 73 2f 6f 77 6e 65 72 20 2d 65 20 24 55 2f  ars/owner -e $U/
6000: 65 78 74 2f 6f 63 78 32 2d 63 67 69 20 2d 64 20  ext/ocx2-cgi -d 
6010: 6a 73 6f 6e 3d 6f 6e 20 2d 2d 64 61 74 61 2d 75  json=on --data-u
6020: 72 6c 65 6e 63 6f 64 65 20 6f 62 6a 65 63 74 69  rlencode objecti
6030: 76 65 3d e2 80 a6 20 2d 64 20 6e 6f 64 65 3d 6e  ve=… -d node=n
6040: 6f 64 65 42 20 2d 2d 64 61 74 61 2d 75 72 6c 65  odeB --data-urle
6050: 6e 63 6f 64 65 20 66 69 65 6c 64 73 3d e2 80 a6  ncode fields=…
6060: 20 24 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69   $U/ext/ocx2-cgi
6070: 2f 63 72 65 61 74 65 60 2e 20 54 68 65 79 20 63  /create`. They c
6080: 61 6d 65 20 62 61 63 6b 20 60 4d 31 20 34 30 33  ame back `M1 403
6090: 20 31 35 2e 30 37 60 2c 20 60 4d 33 20 34 30 33   15.07`, `M3 403
60a0: 20 33 30 2e 31 38 60 2c 20 60 4d 32 20 34 30 33   30.18`, `M2 403
60b0: 20 34 35 2e 32 39 60 2c 20 65 61 63 68 20 73 74   45.29`, each st
60c0: 6f 70 70 65 64 20 61 74 20 60 74 65 73 74 2d 63  opped at `test-c
60d0: 6f 6e 74 65 6e 74 2d 70 75 74 60 20 28 6c 6f 63  ontent-put` (loc
60e0: 6b 65 64 29 2e 20 4e 6f 20 62 6c 6f 62 20 68 6f  ked). No blob ho
60f0: 6c 64 73 20 74 68 65 69 72 20 74 65 78 74 2e 20  lds their text. 
6100: 7c 20 49 6e 20 60 73 72 63 2f 6f 63 78 2f 66 6f  | In `src/ocx/fo
6110: 73 73 69 6c 2f 73 79 6e 63 2e 63 72 3a 32 34 34  ssil/sync.cr:244
6120: 2d 32 35 32 60 20 60 63 68 65 63 6b 65 64 5f 6f  -252` `checked_o
6130: 75 74 60 2c 20 73 6b 69 70 20 74 68 65 20 60 63  ut`, skip the `c
6140: 6c 6f 73 65 60 20 61 66 74 65 72 20 61 20 70 75  lose` after a pu
6150: 74 20 74 68 61 74 20 66 61 69 6c 65 64 20 6f 6e  t that failed on
6160: 20 61 20 6c 6f 63 6b 2c 20 61 6e 64 20 6c 65 61   a lock, and lea
6170: 76 65 20 74 68 65 20 63 6c 65 61 6e 75 70 20 74  ve the cleanup t
6180: 6f 20 74 68 65 20 6d 65 6e 64 20 74 68 61 74 20  o the mend that 
6190: 61 6c 72 65 61 64 79 20 72 65 6d 6f 76 65 73 20  already removes 
61a0: 74 65 6d 70 6f 72 61 72 79 20 63 68 65 63 6b 6f  temporary checko
61b0: 75 74 73 2e 20 41 6c 74 65 72 6e 61 74 69 76 65  uts. Alternative
61c0: 6c 79 2c 20 70 61 73 73 20 61 20 73 68 6f 72 74  ly, pass a short
61d0: 20 60 2d 2d 62 75 73 79 60 2d 73 74 79 6c 65 20   `--busy`-style 
61e0: 74 69 6d 65 6f 75 74 20 74 6f 20 66 6f 73 73 69  timeout to fossi
61f0: 6c 20 63 6f 6d 6d 61 6e 64 73 20 72 75 6e 20 77  l commands run w
6200: 68 69 6c 65 20 68 6f 6c 64 69 6e 67 20 74 68 65  hile holding the
6210: 20 74 75 72 6e 2e 20 45 69 74 68 65 72 20 77 61   turn. Either wa
6220: 79 20 74 68 65 20 74 75 72 6e 20 69 73 20 6e 6f  y the turn is no
6230: 74 20 68 65 6c 64 20 66 6f 72 20 31 35 20 73 20  t held for 15 s 
6240: 70 65 72 20 63 61 6c 6c 65 72 2e 20 53 65 76 65  per caller. Seve
6250: 72 69 74 79 20 69 73 20 6c 6f 77 20 62 65 63 61  rity is low beca
6260: 75 73 65 20 6e 6f 20 63 75 72 72 65 6e 74 20 73  use no current s
6270: 70 65 63 20 70 72 6f 6d 69 73 65 73 20 6f 74 68  pec promises oth
6280: 65 72 77 69 73 65 2e 20 7c 20 60 73 70 65 63 2f  erwise. | `spec/
6290: 6f 63 78 2f 66 6f 73 73 69 6c 5f 73 70 65 63 2e  ocx/fossil_spec.
62a0: 63 72 60 3a 20 74 68 72 65 65 20 77 72 69 74 65  cr`: three write
62b0: 72 73 20 75 6e 64 65 72 20 61 6e 20 6f 75 74 73  rs under an outs
62c0: 69 64 65 20 6c 6f 63 6b 20 65 61 63 68 20 61 6e  ide lock each an
62d0: 73 77 65 72 20 77 69 74 68 69 6e 20 61 62 6f 75  swer within abou
62e0: 74 20 6f 6e 65 20 62 75 73 79 20 74 69 6d 65 6f  t one busy timeo
62f0: 75 74 2e 20 7c 0a 7c 20 31 32 20 7c 20 6c 6f 77  ut. |.| 12 | low
6300: 20 7c 20 2a 2a 54 68 65 20 74 75 72 6e 20 6c 6f   | **The turn lo
6310: 63 6b 20 6c 65 61 76 65 73 20 61 20 60 3c 70 61  ck leaves a `<pa
6320: 74 68 3e 2d 6f 63 78 2e 6c 6f 63 6b 60 20 66 69  th>-ocx.lock` fi
6330: 6c 65 20 62 65 73 69 64 65 20 61 20 72 65 70 6f  le beside a repo
6340: 73 69 74 6f 72 79 20 74 68 61 74 20 64 6f 65 73  sitory that does
6350: 20 6e 6f 74 20 65 78 69 73 74 2e 2a 2a 20 28 43   not exist.** (C
6360: 6f 6e 63 75 72 72 65 6e 63 79 20 66 69 6e 64 69  oncurrency findi
6370: 6e 67 20 37 2e 29 20 7c 20 60 63 64 20 44 2f 63  ng 7.) | `cd D/c
6380: 74 6c 2f 74 79 70 6f 3b 20 63 2e 73 68 20 6f 63  tl/typo; c.sh oc
6390: 78 32 20 2d 2d 6a 73 6f 6e 20 2d 2d 72 65 70 6f  x2 --json --repo
63a0: 73 69 74 6f 72 79 20 44 2f 63 74 6c 2f 74 79 70  sitory D/ctl/typ
63b0: 6f 2f 6e 6f 70 65 2e 66 6f 73 73 69 6c 20 2d 2d  o/nope.fossil --
63c0: 75 73 65 72 20 6f 77 6e 65 72 20 74 68 72 65 61  user owner threa
63d0: 64 20 61 62 63 64 60 20 61 6e 73 77 65 72 65 64  d abcd` answered
63e0: 20 6f 6b 3a 66 61 6c 73 65 20 22 6f 77 6e 65 72   ok:false "owner
63f0: 20 6c 61 63 6b 73 20 77 68 61 74 20 74 68 72 65   lacks what thre
6400: 61 64 20 6e 65 65 64 73 e2 80 a6 22 2c 20 61 6e  ad needs…", an
6410: 64 20 6c 65 66 74 20 60 6e 6f 70 65 2e 66 6f 73  d left `nope.fos
6420: 73 69 6c 2d 6f 63 78 2e 6c 6f 63 6b 60 20 28 30  sil-ocx.lock` (0
6430: 20 62 79 74 65 73 29 2e 20 60 70 6f 6c 6c 20 2d   bytes). `poll -
6440: 2d 6c 6f 67 69 6e 20 6e 6f 64 65 61 60 20 61 6c  -login nodea` al
6450: 73 6f 20 6c 65 66 74 20 60 44 2f 6e 6f 64 65 2f  so left `D/node/
6460: 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 2d 6f 63 78  clone.fossil-ocx
6470: 2e 6c 6f 63 6b 60 20 62 65 66 6f 72 65 20 61 6e  .lock` before an
6480: 79 20 63 6c 6f 6e 65 20 65 78 69 73 74 65 64 2e  y clone existed.
6490: 20 7c 20 49 6e 20 60 73 72 63 2f 6f 63 78 2f 66   | In `src/ocx/f
64a0: 6f 73 73 69 6c 2e 63 72 3a 35 30 60 2c 20 60 72  ossil.cr:50`, `r
64b0: 65 74 75 72 6e 20 79 69 65 6c 64 20 75 6e 6c 65  eturn yield unle
64c0: 73 73 20 72 65 70 6f 73 69 74 6f 72 79 20 26 26  ss repository &&
64d0: 20 46 69 6c 65 2e 65 78 69 73 74 73 3f 28 72 65   File.exists?(re
64e0: 70 6f 73 69 74 6f 72 79 29 60 2e 20 7c 20 60 73  pository)`. | `s
64f0: 70 65 63 2f 6f 63 78 2f 66 6f 73 73 69 6c 5f 73  pec/ocx/fossil_s
6500: 70 65 63 2e 63 72 60 3a 20 61 20 72 65 66 75 73  pec.cr`: a refus
6510: 65 64 20 63 61 6c 6c 20 6f 6e 20 61 20 6d 69 73  ed call on a mis
6520: 73 69 6e 67 20 72 65 70 6f 73 69 74 6f 72 79 20  sing repository 
6530: 6c 65 61 76 65 73 20 69 74 73 20 64 69 72 65 63  leaves its direc
6540: 74 6f 72 79 20 65 6d 70 74 79 2e 20 7c 0a 7c 20  tory empty. |.| 
6550: 31 33 20 7c 20 6c 6f 77 20 7c 20 2a 2a 54 68 65  13 | low | **The
6560: 20 43 4c 49 20 68 61 73 20 6e 6f 20 60 2d 2d 60   CLI has no `--`
6570: 20 6d 61 72 6b 65 72 2c 20 73 6f 20 61 20 76 61   marker, so a va
6580: 6c 75 65 20 73 74 61 72 74 69 6e 67 20 77 69 74  lue starting wit
6590: 68 20 60 2d 2d 60 20 63 61 6e 6e 6f 74 20 62 65  h `--` cannot be
65a0: 20 67 69 76 65 6e 2e 2a 2a 20 28 49 6e 70 75 74   given.** (Input
65b0: 20 66 69 6e 64 69 6e 67 20 31 30 2e 29 20 7c 20   finding 10.) | 
65c0: 60 63 2e 73 68 20 6f 63 78 32 20 2d 2d 6a 73 6f  `c.sh ocx2 --jso
65d0: 6e 20 72 65 61 64 20 2d 2d 77 65 69 72 64 60 20  n read --weird` 
65e0: 67 61 76 65 20 22 6f 63 78 32 3a 20 72 65 61 64  gave "ocx2: read
65f0: 20 68 61 73 20 6e 6f 20 6f 70 74 69 6f 6e 20 2d   has no option -
6600: 2d 77 65 69 72 64 22 20 28 72 63 20 32 29 2e 20  -weird" (rc 2). 
6610: 60 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 65 63 68  `ocx2 --json ech
6620: 6f 20 2d 2d 20 2d 2d 68 65 6c 70 60 20 67 61 76  o -- --help` gav
6630: 65 20 22 65 63 68 6f 20 68 61 73 20 6e 6f 20 6f  e "echo has no o
6640: 70 74 69 6f 6e 20 2d 2d 22 2e 20 7c 20 49 6e 20  ption --". | In 
6650: 60 73 72 63 2f 6f 63 78 2f 63 6c 69 2e 63 72 3a  `src/ocx/cli.cr:
6660: 38 37 60 2c 20 62 65 66 6f 72 65 20 74 68 65 20  87`, before the 
6670: 60 73 74 61 72 74 73 5f 77 69 74 68 3f 28 22 2d  `starts_with?("-
6680: 2d 22 29 60 20 74 65 73 74 2c 20 61 64 64 20 60  -")` test, add `
6690: 69 66 20 61 72 67 20 3d 3d 20 22 2d 2d 22 60 3a  if arg == "--"`:
66a0: 20 74 61 6b 65 20 65 76 65 72 79 20 72 65 6d 61   take every rema
66b0: 69 6e 69 6e 67 20 77 6f 72 64 20 61 73 20 61 20  ining word as a 
66c0: 62 61 72 65 20 77 6f 72 64 2c 20 74 68 65 6e 20  bare word, then 
66d0: 60 62 72 65 61 6b 60 2e 20 7c 20 60 73 70 65 63  `break`. | `spec
66e0: 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 5f 73 70 65  /ocx/command_spe
66f0: 63 2e 63 72 60 3a 20 60 6f 63 78 32 20 72 65 61  c.cr`: `ocx2 rea
6700: 64 20 2d 2d 20 2d 2d 78 60 20 61 6e 73 77 65 72  d -- --x` answer
6710: 73 20 22 6e 6f 20 66 69 6c 65 20 2d 2d 78 22 2e  s "no file --x".
6720: 20 7c 0a 7c 20 31 34 20 7c 20 6c 6f 77 20 7c 20   |.| 14 | low | 
6730: 2a 2a 54 65 73 74 20 65 6e 76 69 72 6f 6e 6d 65  **Test environme
6740: 6e 74 3a 20 6f 63 78 32 20 69 67 6e 6f 72 65 73  nt: ocx2 ignores
6750: 20 60 48 4f 4d 45 60 2c 20 73 6f 20 73 65 74 75   `HOME`, so setu
6760: 70 2e 73 68 27 73 20 63 6c 61 69 6d 20 22 6e 6f  p.sh's claim "no
6770: 20 7e 2f 2e 66 6f 73 73 69 6c 20 6f 75 74 73 69   ~/.fossil outsi
6780: 64 65 20 44 49 52 20 69 73 20 74 6f 75 63 68 65  de DIR is touche
6790: 64 22 20 69 73 20 66 61 6c 73 65 2e 2a 2a 20 28  d" is false.** (
67a0: 49 6e 70 75 74 20 66 69 6e 64 69 6e 67 20 31 31  Input finding 11
67b0: 2e 29 20 7c 20 41 66 74 65 72 20 74 68 65 20 63  .) | After the c
67c0: 6f 6e 66 69 6e 65 64 20 72 65 73 74 61 72 74 2c  onfined restart,
67d0: 20 6f 6e 65 20 60 63 75 72 6c 20 24 55 2f 65 78   one `curl $U/ex
67e0: 74 2f 6f 63 78 32 2d 63 67 69 2f 73 74 61 74 75  t/ocx2-cgi/statu
67f0: 73 3f 6a 73 6f 6e 3d 6f 6e 60 20 63 72 65 61 74  s?json=on` creat
6800: 65 64 20 60 44 2f 61 63 63 74 2f 2e 66 6f 73 73  ed `D/acct/.foss
6810: 69 6c 60 20 28 38 31 39 32 20 62 79 74 65 73 29  il` (8192 bytes)
6820: 2c 20 65 76 65 6e 20 74 68 6f 75 67 68 20 74 68  , even though th
6830: 65 20 73 65 72 76 65 72 20 72 61 6e 20 77 69 74  e server ran wit
6840: 68 20 60 48 4f 4d 45 3d 44 2f 68 6f 6d 65 60 2e  h `HOME=D/home`.
6850: 20 60 74 6f 6f 6c 73 2f 6f 63 78 32 2e 63 72 3a   `tools/ocx2.cr:
6860: 33 30 60 20 74 61 6b 65 73 20 74 68 65 20 68 6f  30` takes the ho
6870: 6d 65 20 66 72 6f 6d 20 74 68 65 20 61 63 63 6f  me from the acco
6880: 75 6e 74 20 64 61 74 61 62 61 73 65 20 6f 6e 20  unt database on 
6890: 70 75 72 70 6f 73 65 20 28 22 46 6f 73 73 69 6c  purpose ("Fossil
68a0: 20 6b 65 65 70 73 20 69 74 73 20 73 65 74 74 69   keeps its setti
68b0: 6e 67 73 20 69 6e 20 74 68 65 20 68 6f 6d 65 20  ngs in the home 
68c0: 74 68 65 20 61 63 63 6f 75 6e 74 20 64 61 74 61  the account data
68d0: 62 61 73 65 20 6e 61 6d 65 73 22 29 2c 20 73 6f  base names"), so
68e0: 20 74 68 65 20 70 72 6f 67 72 61 6d 20 69 73 20   the program is 
68f0: 77 6f 72 6b 69 6e 67 20 61 73 20 64 65 73 69 67  working as desig
6900: 6e 65 64 2e 20 54 68 65 20 6f 74 68 65 72 20 74  ned. The other t
6910: 65 73 74 65 72 73 20 77 68 6f 20 72 61 6e 20 75  esters who ran u
6920: 6e 63 6f 6e 66 69 6e 65 64 20 77 72 6f 74 65 20  nconfined wrote 
6930: 74 68 65 20 72 65 61 6c 20 60 2f 72 6f 6f 74 2f  the real `/root/
6940: 2e 66 6f 73 73 69 6c 60 20 28 63 68 61 6e 67 65  .fossil` (change
6950: 64 20 61 74 20 31 37 3a 32 37 29 2e 20 7c 20 49  d at 17:27). | I
6960: 6e 20 60 73 63 72 61 74 63 68 70 61 64 2f 61 64  n `scratchpad/ad
6970: 76 65 72 73 61 72 79 2f 73 65 74 75 70 2e 73 68  versary/setup.sh
6980: 60 2c 20 77 72 69 74 65 20 60 73 74 61 72 74 2e  `, write `start.
6990: 73 68 60 20 74 6f 20 72 75 6e 20 60 62 77 72 61  sh` to run `bwra
69a0: 70 20 2d 2d 64 65 76 2d 62 69 6e 64 20 2f 20 2f  p --dev-bind / /
69b0: 20 2d 2d 62 69 6e 64 20 44 49 52 2f 61 63 63 74   --bind DIR/acct
69c0: 20 2f 72 6f 6f 74 20 2d 2d 20 66 6f 73 73 69 6c   /root -- fossil
69d0: 20 73 65 72 76 65 72 20 e2 80 a6 60 20 28 61 73   server …` (as
69e0: 20 60 44 2f 73 74 61 72 74 2d 63 6f 6e 66 69 6e   `D/start-confin
69f0: 65 64 2e 73 68 60 20 64 6f 65 73 29 2c 20 61 64  ed.sh` does), ad
6a00: 64 20 60 44 49 52 2f 63 2e 73 68 60 20 66 6f 72  d `DIR/c.sh` for
6a10: 20 43 4c 49 20 63 61 6c 6c 73 2c 20 61 6e 64 20   CLI calls, and 
6a20: 63 6f 72 72 65 63 74 20 74 68 65 20 75 73 61 67  correct the usag
6a30: 65 20 6e 6f 74 65 2e 20 7c 20 52 65 72 75 6e 20  e note. | Rerun 
6a40: 73 65 74 75 70 2c 20 74 68 65 6e 20 6f 6e 65 20  setup, then one 
6a50: 73 74 61 74 75 73 20 63 61 6c 6c 3a 20 60 2f 72  status call: `/r
6a60: 6f 6f 74 2f 2e 66 6f 73 73 69 6c 60 20 6d 74 69  oot/.fossil` mti
6a70: 6d 65 20 75 6e 63 68 61 6e 67 65 64 20 61 6e 64  me unchanged and
6a80: 20 60 44 49 52 2f 61 63 63 74 2f 2e 66 6f 73 73   `DIR/acct/.foss
6a90: 69 6c 60 20 70 72 65 73 65 6e 74 2e 20 7c 0a 0a  il` present. |..
6aa0: 23 23 20 44 72 6f 70 70 65 64 0a 0a 2d 20 2a 2a  ## Dropped..- **
6ab0: 54 68 65 20 73 65 63 72 65 74 20 74 6f 6f 6c 20  The secret tool 
6ac0: 63 61 6e 6e 6f 74 20 62 65 20 72 65 61 63 68 65  cannot be reache
6ad0: 64 20 66 72 6f 6d 20 74 68 65 20 77 65 62 20 70  d from the web p
6ae0: 61 67 65 2a 2a 20 28 70 72 69 76 61 63 79 20 66  age** (privacy f
6af0: 69 6e 64 69 6e 67 20 32 29 2e 20 49 74 20 64 6f  inding 2). It do
6b00: 65 73 20 6e 6f 74 20 72 65 70 72 6f 64 75 63 65  es not reproduce
6b10: 20 61 73 20 73 74 61 74 65 64 2e 20 4f 6e 6c 79   as stated. Only
6b20: 20 61 20 68 61 6e 64 2d 74 79 70 65 64 20 47 45   a hand-typed GE
6b30: 54 20 77 69 74 68 20 60 6e 61 6d 65 60 20 69 6e  T with `name` in
6b40: 20 74 68 65 20 71 75 65 72 79 20 66 61 69 6c 73   the query fails
6b50: 20 28 60 73 65 63 72 65 74 3f 6e 61 6d 65 3d 74   (`secret?name=t
6b60: 75 6e 6e 65 6c 26 76 61 6c 75 65 3d 78 60 20 67  unnel&value=x` g
6b70: 69 76 65 73 20 34 30 34 2c 20 62 65 63 61 75 73  ives 404, becaus
6b80: 65 20 46 6f 73 73 69 6c 20 74 61 6b 65 73 20 60  e Fossil takes `
6b90: 6e 61 6d 65 60 20 66 72 6f 6d 20 74 68 65 20 71  name` from the q
6ba0: 75 65 72 79 20 75 6e 64 65 72 20 2f 65 78 74 29  uery under /ext)
6bb0: 2e 20 54 68 65 20 63 61 72 64 27 73 20 66 6f 72  . The card's for
6bc0: 6d 20 69 73 20 60 3c 66 6f 72 6d 20 6d 65 74 68  m is `<form meth
6bd0: 6f 64 3d 22 50 4f 53 54 22 20 61 63 74 69 6f 6e  od="POST" action
6be0: 3d 22 6f 63 78 32 2d 63 67 69 2f 73 65 63 72 65  ="ocx2-cgi/secre
6bf0: 74 22 3e 60 2c 20 61 6e 64 20 46 6f 73 73 69 6c  t">`, and Fossil
6c00: 20 64 6f 65 73 20 6e 6f 74 20 74 61 6b 65 20 60   does not take `
6c10: 6e 61 6d 65 60 20 66 72 6f 6d 20 61 20 50 4f 53  name` from a POS
6c20: 54 20 62 6f 64 79 2e 20 60 63 75 72 6c 20 2d 62  T body. `curl -b
6c30: 20 6f 77 6e 65 72 20 2d 65 20 24 55 2f 65 78 74   owner -e $U/ext
6c40: 2f 6f 63 78 32 2d 63 67 69 20 2d 58 20 50 4f 53  /ocx2-cgi -X POS
6c50: 54 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63 6f  T --data-urlenco
6c60: 64 65 20 6e 61 6d 65 3d 74 75 6e 6e 65 6c 20 2d  de name=tunnel -
6c70: 2d 64 61 74 61 2d 75 72 6c 65 6e 63 6f 64 65 20  -data-urlencode 
6c80: 76 61 6c 75 65 3d 73 63 72 61 74 63 68 76 61 6c  value=scratchval
6c90: 75 65 31 20 2d 64 20 6a 73 6f 6e 3d 6f 6e 20 24  ue1 -d json=on $
6ca0: 55 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f 73  U/ext/ocx2-cgi/s
6cb0: 65 63 72 65 74 60 20 61 6e 73 77 65 72 65 64 20  ecret` answered 
6cc0: 32 30 30 20 60 7b 22 6f 6b 22 3a 74 72 75 65 2c  200 `{"ok":true,
6cd0: e2 80 a6 22 72 65 73 75 6c 74 22 3a 7b 22 6e 61  …"result":{"na
6ce0: 6d 65 22 3a 22 74 75 6e 6e 65 6c 22 7d 7d 60 2c  me":"tunnel"}}`,
6cf0: 20 61 6e 64 20 74 68 65 20 63 6f 6e 66 69 67 20   and the config 
6d00: 72 6f 77 20 60 6f 63 78 2d 73 65 63 72 65 74 2d  row `ocx-secret-
6d10: 74 75 6e 6e 65 6c 60 20 65 78 69 73 74 73 2e 20  tunnel` exists. 
6d20: 41 20 47 45 54 20 6f 66 20 61 20 77 72 69 74 69  A GET of a writi
6d30: 6e 67 20 74 6f 6f 6c 20 77 6f 75 6c 64 20 62 65  ng tool would be
6d40: 20 61 20 64 72 79 20 72 75 6e 20 61 6e 79 77 61   a dry run anywa
6d50: 79 2e 0a 2d 20 2a 2a 72 65 63 65 69 70 74 20 73  y..- **receipt s
6d60: 68 6f 77 73 20 61 6e 79 20 75 73 65 72 27 73 20  hows any user's 
6d70: 63 61 70 61 62 69 6c 69 74 69 65 73 20 74 6f 20  capabilities to 
6d80: 75 6e 61 75 74 68 65 6e 74 69 63 61 74 65 64 20  unauthenticated 
6d90: 63 61 6c 6c 65 72 73 2a 2a 20 28 70 72 69 76 61  callers** (priva
6da0: 63 79 20 66 69 6e 64 69 6e 67 20 33 2c 20 61 6e  cy finding 3, an
6db0: 64 20 74 68 65 20 61 75 74 68 6f 72 69 74 79 20  d the authority 
6dc0: 72 65 70 6f 72 74 27 73 20 6e 6f 74 65 20 32 2c  report's note 2,
6dd0: 20 6d 65 72 67 65 64 29 2e 20 54 68 65 20 64 6f   merged). The do
6de0: 63 73 20 73 61 79 20 74 68 69 73 20 69 73 20 69  cs say this is i
6df0: 6e 74 65 6e 64 65 64 2e 20 60 64 6f 63 73 2f 69  ntended. `docs/i
6e00: 6e 74 65 72 66 61 63 65 73 2e 6d 64 3a 35 37 60  nterfaces.md:57`
6e10: 20 73 61 79 73 20 72 65 63 65 69 70 74 20 6e 65   says receipt ne
6e20: 65 64 73 20 6e 6f 20 63 61 70 61 62 69 6c 69 74  eds no capabilit
6e30: 79 20 61 6e 64 20 67 69 76 65 73 20 22 66 6f 72  y and gives "for
6e40: 20 60 2d 2d 63 61 70 61 62 69 6c 69 74 69 65 73   `--capabilities
6e50: 2d 6f 66 60 2c 20 74 68 61 74 20 75 73 65 72 27  -of`, that user'
6e60: 73 20 63 61 70 61 62 69 6c 69 74 69 65 73 22 2c  s capabilities",
6e70: 20 77 69 74 68 20 52 65 61 64 20 28 60 6f 60 29   with Read (`o`)
6e80: 20 61 73 20 74 68 65 20 6f 6e 6c 79 20 67 61 74   as the only gat
6e90: 65 2e 20 4e 6f 64 65 73 20 61 6e 64 20 63 6c 6f  e. Nodes and clo
6ea0: 6e 65 73 20 64 65 70 65 6e 64 20 6f 6e 20 61 73  nes depend on as
6eb0: 6b 69 6e 67 20 69 74 20 75 6e 73 69 67 6e 65 64  king it unsigned
6ec0: 20 28 74 68 65 20 70 6f 6c 6c 20 72 6f 77 2c 20   (the poll row, 
6ed0: 61 6e 64 20 60 53 65 72 76 65 72 3a 3a 41 73 6b  and `Server::Ask
6ee0: 65 64 2e 63 61 70 61 62 69 6c 69 74 69 65 73 5f  ed.capabilities_
6ef0: 61 74 60 29 2e 0a 2d 20 2a 2a 43 4c 49 20 72 65  at`)..- **CLI re
6f00: 6c 65 61 73 65 20 6f 70 65 72 61 74 69 6f 6e 73  lease operations
6f10: 20 6f 6e 20 61 20 63 6c 6f 6e 65 20 70 61 73 73   on a clone pass
6f20: 20 74 68 65 20 73 65 74 75 70 20 67 61 74 65 2a   the setup gate*
6f30: 2a 20 28 74 68 65 20 61 75 74 68 6f 72 69 74 79  * (the authority
6f40: 20 72 65 70 6f 72 74 27 73 20 6e 6f 74 65 20 31   report's note 1
6f50: 29 2e 20 54 68 65 20 64 6f 63 73 20 73 61 79 20  ). The docs say 
6f60: 74 68 69 73 20 69 73 20 69 6e 74 65 6e 64 65 64  this is intended
6f70: 2e 20 60 64 6f 63 73 2f 69 6e 74 65 72 66 61 63  . `docs/interfac
6f80: 65 73 2e 6d 64 60 20 28 74 68 65 20 6f 6e 65 2d  es.md` (the one-
6f90: 70 72 6f 67 72 61 6d 20 72 6f 77 29 20 73 61 79  program row) say
6fa0: 73 20 22 74 68 65 20 63 6f 6d 6d 61 6e 64 20 6c  s "the command l
6fb0: 69 6e 65 20 6b 65 65 70 69 6e 67 20 74 68 65 20  ine keeping the 
6fc0: 63 6c 6f 6e 65 27 73 22 20 63 61 70 61 62 69 6c  clone's" capabil
6fd0: 69 74 69 65 73 2c 20 61 6e 64 20 60 73 72 63 2f  ities, and `src/
6fe0: 6f 63 78 2f 65 6e 74 72 79 2e 63 72 60 20 73 61  ocx/entry.cr` sa
6ff0: 79 73 20 74 68 65 20 73 61 6e 64 62 6f 78 20 69  ys the sandbox i
7000: 73 20 77 68 61 74 20 6c 69 6d 69 74 73 20 61 6e  s what limits an
7010: 20 61 67 65 6e 74 2e 0a 2d 20 2a 2a 54 68 65 20   agent..- **The 
7020: 74 75 72 6e 20 6c 6f 63 6b 20 70 6f 6c 6c 73 20  turn lock polls 
7030: 65 76 65 72 79 20 31 30 30 20 6d 73 20 69 6e 73  every 100 ms ins
7040: 74 65 61 64 20 6f 66 20 77 61 69 74 69 6e 67 20  tead of waiting 
7050: 69 6e 20 74 68 65 20 6b 65 72 6e 65 6c 2a 2a 20  in the kernel** 
7060: 28 63 6f 6e 63 75 72 72 65 6e 63 79 20 66 69 6e  (concurrency fin
7070: 64 69 6e 67 20 35 29 2e 20 54 68 65 20 62 65 68  ding 5). The beh
7080: 61 76 69 6f 75 72 20 69 73 20 72 65 61 6c 3a 20  aviour is real: 
7090: 43 72 79 73 74 61 6c 27 73 20 60 66 6c 6f 63 6b  Crystal's `flock
70a0: 5f 65 78 63 6c 75 73 69 76 65 60 20 69 73 20 60  _exclusive` is `
70b0: 75 6e 74 69 6c 20 66 6c 6f 63 6b 28 6f 70 5c 7c  until flock(op\|
70c0: 4e 42 29 3b 20 73 6c 65 65 70 20 30 2e 31 2e 73  NB); sleep 0.1.s
70d0: 65 63 6f 6e 64 73 60 2c 20 61 74 20 60 2f 75 73  econds`, at `/us
70e0: 72 2f 6c 69 62 2f 63 72 79 73 74 61 6c 2f 63 6f  r/lib/crystal/co
70f0: 72 65 2f 63 72 79 73 74 61 6c 2f 73 79 73 74 65  re/crystal/syste
7100: 6d 2f 75 6e 69 78 2f 66 69 6c 65 5f 64 65 73 63  m/unix/file_desc
7110: 72 69 70 74 6f 72 2e 63 72 3a 31 38 34 2d 31 39  riptor.cr:184-19
7120: 32 60 2e 20 42 75 74 20 74 68 65 20 6f 6e 6c 79  2`. But the only
7130: 20 72 65 71 75 69 72 65 6d 65 6e 74 20 69 74 20   requirement it 
7140: 62 72 65 61 6b 73 20 69 73 20 69 6e 20 60 64 6f  breaks is in `do
7150: 63 73 2f 70 72 6f 74 6f 63 6f 6c 2d 76 32 2d 64  cs/protocol-v2-d
7160: 72 61 66 74 2d 6f 77 6e 65 72 2e 6d 64 60 2c 20  raft-owner.md`, 
7170: 77 68 69 63 68 20 73 61 79 73 20 22 4e 6f 74 68  which says "Noth
7180: 69 6e 67 20 6f 66 20 69 74 20 69 73 20 62 75 69  ing of it is bui
7190: 6c 74 22 2e 20 4d 75 74 75 61 6c 20 65 78 63 6c  lt". Mutual excl
71a0: 75 73 69 6f 6e 20 68 6f 6c 64 73 2c 20 73 6f 20  usion holds, so 
71b0: 74 68 69 73 20 62 65 6c 6f 6e 67 73 20 74 6f 20  this belongs to 
71c0: 76 32 20 77 6f 72 6b 2e 0a 0a 23 23 20 57 68 61  v2 work...## Wha
71d0: 74 20 68 65 6c 64 2c 20 72 65 63 68 65 63 6b 65  t held, rechecke
71e0: 64 20 68 65 72 65 0a 0a 2d 20 2a 2a 43 61 70 61  d here..- **Capa
71f0: 62 69 6c 69 74 79 20 67 61 74 65 3a 2a 2a 20 61  bility gate:** a
7200: 6e 20 75 6e 6b 6e 6f 77 6e 20 60 66 6f 6f 3d 62  n unknown `foo=b
7210: 61 72 60 20 6f 6e 20 73 65 63 72 65 74 20 67 61  ar` on secret ga
7220: 76 65 20 34 30 33 2e 20 61 70 70 72 6f 76 65 20  ve 403. approve 
7230: 77 6f 72 6b 65 64 20 6f 6e 6c 79 20 61 73 20 6f  worked only as o
7240: 77 6e 65 72 2c 20 62 79 20 50 4f 53 54 20 77 69  wner, by POST wi
7250: 74 68 20 74 68 69 73 20 73 69 74 65 27 73 20 52  th this site's R
7260: 65 66 65 72 65 72 2e 0a 2d 20 2a 2a 49 64 65 6e  eferer..- **Iden
7270: 74 69 74 79 3a 2a 2a 20 60 73 74 61 74 75 73 3f  tity:** `status?
7280: 6e 61 6d 65 3d 77 68 6f 60 20 72 75 6e 73 20 46  name=who` runs F
7290: 6f 73 73 69 6c 27 73 20 60 77 68 6f 60 20 73 63  ossil's `who` sc
72a0: 72 69 70 74 20 28 22 76 69 65 77 65 72 3d 20 63  ript ("viewer= c
72b0: 61 70 61 62 69 6c 69 74 69 65 73 3d 67 68 6a 6f  apabilities=ghjo
72c0: 72 7a 22 29 2c 20 6e 6f 74 20 4f 43 58 2c 20 73  rz"), not OCX, s
72d0: 6f 20 69 64 65 6e 74 69 74 79 20 73 74 69 6c 6c  o identity still
72e0: 20 63 6f 6d 65 73 20 66 72 6f 6d 20 46 6f 73 73   comes from Foss
72f0: 69 6c 2e 0a 2d 20 2a 2a 53 79 6d 6c 69 6e 6b 73  il..- **Symlinks
7300: 3a 2a 2a 20 60 72 65 61 64 60 20 74 68 72 6f 75  :** `read` throu
7310: 67 68 20 61 20 6c 69 6e 6b 20 74 6f 20 61 6e 20  gh a link to an 
7320: 65 78 69 73 74 69 6e 67 20 6f 75 74 73 69 64 65  existing outside
7330: 20 66 69 6c 65 20 69 73 20 72 65 66 75 73 65 64   file is refused
7340: 2e 20 60 65 64 69 74 60 20 75 6e 64 65 72 20 61  . `edit` under a
7350: 20 64 61 6e 67 6c 69 6e 67 20 64 69 72 65 63 74   dangling direct
7360: 6f 72 79 20 6c 69 6e 6b 20 66 61 69 6c 73 2c 20  ory link fails, 
7370: 62 75 74 20 69 74 73 20 72 65 61 73 6f 6e 20 69  but its reason i
7380: 73 20 61 6e 20 69 6e 74 65 72 6e 61 6c 20 22 55  s an internal "U
7390: 6e 61 62 6c 65 20 74 6f 20 63 72 65 61 74 65 20  nable to create 
73a0: 64 69 72 65 63 74 6f 72 79 20 e2 80 a6 20 46 69  directory … Fi
73b0: 6c 65 20 65 78 69 73 74 73 22 20 28 66 69 6e 64  le exists" (find
73c0: 69 6e 67 20 33 20 63 6f 76 65 72 73 20 74 68 65  ing 3 covers the
73d0: 20 6d 65 73 73 61 67 65 29 2e 0a 2d 20 2a 2a 63   message)..- **c
73e0: 6f 6c 6c 65 63 74 3a 2a 2a 20 74 68 65 20 63 6f  ollect:** the co
73f0: 64 65 20 77 6f 72 6b 73 20 6f 6e 6c 79 20 61 66  de works only af
7400: 74 65 72 20 61 70 70 72 6f 76 61 6c 2c 20 61 6e  ter approval, an
7410: 64 20 74 68 65 20 50 4f 53 54 20 70 61 74 68 20  d the POST path 
7420: 61 6e 73 77 65 72 73 20 74 68 65 20 70 61 73 73  answers the pass
7430: 77 6f 72 64 2c 20 61 73 20 60 72 65 67 69 73 74  word, as `regist
7440: 65 72 60 20 75 73 65 73 20 69 74 2e 0a 2d 20 2a  er` uses it..- *
7450: 2a 43 6f 6e 63 75 72 72 65 6e 63 79 3a 2a 2a 20  *Concurrency:** 
7460: 77 69 74 68 20 6e 6f 20 6f 75 74 73 69 64 65 20  with no outside 
7470: 6c 6f 63 6b 2c 20 6e 6f 74 68 69 6e 67 20 72 61  lock, nothing ra
7480: 6e 20 6f 75 74 20 6f 66 20 6f 72 64 65 72 2e 20  n out of order. 
7490: 45 61 63 68 20 77 72 69 74 65 20 74 68 61 74 20  Each write that 
74a0: 77 61 73 20 74 6f 6c 64 20 6f 6b 20 77 61 73 20  was told ok was 
74b0: 77 72 69 74 74 65 6e 20 6f 6e 63 65 20 61 6e 64  written once and
74c0: 20 69 6e 64 65 78 65 64 2e 20 54 68 65 20 6c 6f   indexed. The lo
74d0: 63 6b 65 64 20 77 65 62 20 63 72 65 61 74 65 73  cked web creates
74e0: 20 77 72 6f 74 65 20 6e 6f 74 68 69 6e 67 2e 20   wrote nothing. 
74f0: 4e 6f 20 74 65 6d 70 6f 72 61 72 79 20 60 2f 74  No temporary `/t
7500: 6d 70 2f 2a 6f 63 78 2d 63 68 65 63 6b 6f 75 74  mp/*ocx-checkout
7510: 2a 60 20 64 69 72 65 63 74 6f 72 79 20 69 73 20  *` directory is 
7520: 6c 65 66 74 2e 0a 2d 20 2a 2a 4d 43 50 20 48 54  left..- **MCP HT
7530: 54 50 3a 2a 2a 20 69 74 20 6b 65 65 70 73 20 73  TP:** it keeps s
7540: 65 72 76 69 6e 67 20 61 66 74 65 72 20 65 61 63  erving after eac
7550: 68 20 35 30 30 2c 20 61 6e 64 20 74 68 65 20 6e  h 500, and the n
7560: 65 78 74 20 60 6f 63 78 5f 65 63 68 6f 60 20 67  ext `ocx_echo` g
7570: 61 76 65 20 32 30 30 2e 20 54 68 65 20 73 74 64  ave 200. The std
7580: 69 6f 20 73 65 72 76 65 72 20 64 6f 65 73 20 6e  io server does n
7590: 6f 74 20 6b 65 65 70 20 73 65 72 76 69 6e 67 20  ot keep serving 
75a0: 28 66 69 6e 64 69 6e 67 20 34 29 2e 0a 0a 23 23  (finding 4)...##
75b0: 20 4e 6f 74 65 73 20 6f 6e 20 74 68 65 20 72 75   Notes on the ru
75c0: 6e 0a 0a 2d 20 2a 2a 54 68 65 20 6f 74 68 65 72  n..- **The other
75d0: 20 74 65 73 74 65 72 73 27 20 65 6e 76 69 72 6f   testers' enviro
75e0: 6e 6d 65 6e 74 73 3a 2a 2a 20 74 68 65 20 61 75  nments:** the au
75f0: 74 68 6f 72 69 74 79 20 72 65 70 6f 72 74 20 73  thority report s
7600: 61 79 73 20 69 74 73 20 63 6c 65 61 6e 75 70 20  ays its cleanup 
7610: 6b 69 6c 6c 65 64 20 74 77 6f 20 60 6f 63 78 32  killed two `ocx2
7620: 20 2d 2d 6d 63 70 2d 68 74 74 70 60 20 70 72 6f   --mcp-http` pro
7630: 63 65 73 73 65 73 20 6f 6e 20 31 38 39 34 31 20  cesses on 18941 
7640: 62 65 6c 6f 6e 67 69 6e 67 20 74 6f 20 61 6e 6f  belonging to ano
7650: 74 68 65 72 20 73 65 73 73 69 6f 6e 20 28 50 49  ther session (PI
7660: 44 73 20 32 32 35 30 38 34 30 20 61 6e 64 20 32  Ds 2250840 and 2
7670: 32 35 30 38 34 32 29 2e 20 54 68 65 20 63 6f 6e  250842). The con
7680: 63 75 72 72 65 6e 63 79 20 74 65 73 74 65 72 20  currency tester 
7690: 72 61 6e 20 6f 63 78 32 20 75 6e 63 6f 6e 66 69  ran ocx2 unconfi
76a0: 6e 65 64 2c 20 73 6f 20 69 74 20 77 72 6f 74 65  ned, so it wrote
76b0: 20 74 68 65 20 72 65 61 6c 20 60 2f 72 6f 6f 74   the real `/root
76c0: 2f 2e 66 6f 73 73 69 6c 60 20 28 66 69 6e 64 69  /.fossil` (findi
76d0: 6e 67 20 31 34 29 2e 0a 2d 20 2a 2a 57 72 69 74  ng 14)..- **Writ
76e0: 65 73 20 69 6e 20 74 72 69 61 67 65 3a 2a 2a 20  es in triage:** 
76f0: 68 61 6c 66 2d 77 72 69 74 74 65 6e 20 72 75 6e  half-written run
7700: 73 2c 20 70 6f 73 74 73 20 61 6e 64 20 74 69 63  s, posts and tic
7710: 6b 65 74 20 63 6f 6d 6d 65 6e 74 73 20 6f 6e 20  ket comments on 
7720: 74 68 65 20 74 72 69 61 67 65 20 73 65 72 76 65  the triage serve
7730: 72 20 61 6e 64 20 69 6e 20 69 76 79 27 73 20 63  r and in ivy's c
7740: 6c 6f 6e 65 2c 20 74 68 65 20 6e 6f 64 65 20 6e  lone, the node n
7750: 6f 64 65 61 2c 20 61 6e 64 20 74 68 65 20 6c 6f  odea, and the lo
7760: 67 69 6e 73 20 6c 61 62 2d 37 20 61 6e 64 20 6e  gins lab-7 and n
7770: 6f 64 65 61 20 28 61 70 70 72 6f 76 65 64 29 2e  odea (approved).
7780: 20 41 6c 73 6f 20 74 68 65 20 73 65 63 72 65 74   Also the secret
7790: 20 60 74 75 6e 6e 65 6c 3d 73 63 72 61 74 63 68   `tunnel=scratch
77a0: 76 61 6c 75 65 31 60 20 69 6e 20 74 68 65 20 74  value1` in the t
77b0: 72 69 61 67 65 20 72 65 70 6f 73 69 74 6f 72 79  riage repository
77c0: 2c 20 74 68 65 20 74 65 73 74 20 63 6c 6f 6e 65  , the test clone
77d0: 20 60 44 2f 74 2f 74 72 69 63 6b 60 2c 20 61 6e   `D/t/trick`, an
77e0: 64 20 60 44 2f 74 2f 4f 55 54 53 49 44 45 2d 77  d `D/t/OUTSIDE-w
77f0: 72 69 74 74 65 6e 2e 74 78 74 60 2e 20 49 20 72  ritten.txt`. I r
7800: 65 6d 6f 76 65 64 20 74 68 65 20 73 79 6d 6c 69  emoved the symli
7810: 6e 6b 73 20 49 20 6d 61 64 65 20 69 6e 20 69 76  nks I made in iv
7820: 79 27 73 20 63 68 65 63 6b 6f 75 74 2e 0a 2d 20  y's checkout..- 
7830: 2a 2a 4e 6f 74 68 69 6e 67 20 6f 75 74 73 69 64  **Nothing outsid
7840: 65 20 74 68 65 20 73 63 72 61 74 63 68 20 61 72  e the scratch ar
7850: 65 61 3a 2a 2a 20 6e 6f 74 68 69 6e 67 20 77 61  ea:** nothing wa
7860: 73 20 63 6f 6d 6d 69 74 74 65 64 2c 20 73 74 61  s committed, sta
7870: 67 65 64 2c 20 61 63 63 65 70 74 65 64 2c 20 70  ged, accepted, p
7880: 6f 73 74 65 64 2c 20 6f 72 20 73 79 6e 63 65 64  osted, or synced
7890: 20 6f 75 74 73 69 64 65 20 74 72 69 61 67 65 2e   outside triage.
78a0: 20 45 76 65 72 79 20 72 65 71 75 65 73 74 20 77   Every request w
78b0: 65 6e 74 20 74 6f 20 31 32 37 2e 30 2e 30 2e 31  ent to 127.0.0.1
78c0: 2e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
78d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
78e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
78f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7910: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7920: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7930: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7940: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7950: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7960: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7970: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7990: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
79f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7a00: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
7a10: 2f 73 65 74 75 70 2d 72 65 70 6f 72 74 2e 6a 73  /setup-report.js
7a20: 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00  on..............
7a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7a40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7a50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7a60: 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
7a70: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
7a80: 30 30 31 34 35 37 33 00 31 35 32 36 35 32 30 33  0014573.15265203
7a90: 36 37 36 00 30 31 36 34 32 32 00 20 30 00 00 00  676.016422. 0...
7aa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7ab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7ac0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7ad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7ae0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7af0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b00: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
7b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b20: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
7b30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
7c00: 7b 0a 20 22 73 63 72 69 70 74 22 3a 20 22 2f 74  {. "script": "/t
7c10: 6d 70 2f 63 6c 61 75 64 65 2d 30 2f 2d 76 61 72  mp/claude-0/-var
7c20: 2d 6c 69 62 2d 6f 63 78 2d 61 67 65 6e 74 73 2d  -lib-ocx-agents-
7c30: 6f 70 75 73 2d 6f 63 78 32 2d 70 72 6f 6a 65 63  opus-ocx2-projec
7c40: 74 73 2d 6f 6c 6c 61 6d 61 2d 62 32 64 65 38 62  ts-ollama-b2de8b
7c50: 30 63 32 63 36 37 30 30 65 62 35 63 36 38 36 62  0c2c6700eb5c686b
7c60: 31 37 34 37 62 35 61 61 61 31 65 32 64 32 64 30  1747b5aaa1e2d2d0
7c70: 31 33 37 30 61 63 35 35 66 32 65 35 61 31 35 31  1370ac55f2e5a151
7c80: 61 36 37 65 30 33 62 34 38 61 2f 33 66 37 63 66  a67e03b48a/3f7cf
7c90: 65 32 35 2d 32 38 61 61 2d 34 63 35 35 2d 38 32  e25-28aa-4c55-82
7ca0: 37 63 2d 62 63 30 36 31 38 64 61 38 31 65 36 2f  7c-bc0618da81e6/
7cb0: 73 63 72 61 74 63 68 70 61 64 2f 61 64 76 65 72  scratchpad/adver
7cc0: 73 61 72 79 2f 73 65 74 75 70 2e 73 68 22 2c 0a  sary/setup.sh",.
7cd0: 20 22 75 73 61 67 65 22 3a 20 22 52 75 6e 3a 20   "usage": "Run: 
7ce0: 73 65 74 75 70 2e 73 68 20 44 49 52 20 50 4f 52  setup.sh DIR POR
7cf0: 54 2e 20 44 49 52 20 6d 75 73 74 20 6e 6f 74 20  T. DIR must not 
7d00: 65 78 69 73 74 20 6f 72 20 6d 75 73 74 20 62 65  exist or must be
7d10: 20 65 6d 70 74 79 3b 20 50 4f 52 54 20 6d 75 73   empty; PORT mus
7d20: 74 20 62 65 20 66 72 65 65 2e 20 54 68 65 20 73  t be free. The s
7d30: 63 72 69 70 74 20 72 65 66 75 73 65 73 20 69 66  cript refuses if
7d40: 20 61 6e 79 74 68 69 6e 67 20 61 6c 72 65 61 64   anything alread
7d50: 79 20 61 6e 73 77 65 72 73 20 6f 6e 20 31 32 37  y answers on 127
7d60: 2e 30 2e 30 2e 31 3a 50 4f 52 54 2e 20 41 20 66  .0.0.1:PORT. A f
7d70: 75 6c 6c 20 72 75 6e 20 74 61 6b 65 73 20 61 62  ull run takes ab
7d80: 6f 75 74 20 30 2e 36 20 73 2e 20 57 68 65 6e 20  out 0.6 s. When 
7d90: 69 74 20 66 69 6e 69 73 68 65 73 2c 20 74 68 65  it finishes, the
7da0: 20 73 65 72 76 65 72 20 69 73 20 73 74 69 6c 6c   server is still
7db0: 20 72 75 6e 6e 69 6e 67 2e 5c 6e 5c 6e 57 68 61   running.\n\nWha
7dc0: 74 20 69 74 20 62 75 69 6c 64 73 20 69 6e 20 44  t it builds in D
7dd0: 49 52 3a 5c 6e 2d 20 2a 2a 54 68 65 20 70 72 6f  IR:\n- **The pro
7de0: 67 72 61 6d 2c 20 63 6f 70 69 65 64 20 69 6e 74  gram, copied int
7df0: 6f 20 61 20 73 63 72 61 74 63 68 20 72 65 6c 65  o a scratch rele
7e00: 61 73 65 20 72 6f 6f 74 2e 2a 2a 20 54 68 65 20  ase root.** The 
7e10: 73 74 61 67 65 64 20 70 72 6f 67 72 61 6d 20 69  staged program i
7e20: 73 20 63 6f 70 69 65 64 20 28 73 61 6d 65 20 73  s copied (same s
7e30: 68 61 32 35 36 2c 20 36 61 65 66 38 61 64 37 5c  ha256, 6aef8ad7\
7e40: 75 32 30 32 36 29 20 74 6f 20 44 49 52 2f 72 6f  u2026) to DIR/ro
7e50: 6f 74 2f 63 75 72 72 65 6e 74 2f 6f 63 78 32 20  ot/current/ocx2 
7e60: 61 6e 64 20 74 6f 20 44 49 52 2f 72 6f 6f 74 2f  and to DIR/root/
7e70: 73 74 61 67 65 64 2f 6e 65 78 74 2f 6f 63 78 32  staged/next/ocx2
7e80: 2e 20 54 68 65 20 6c 69 6e 6b 73 20 61 72 65 20  . The links are 
7e90: 65 78 74 2f 6f 63 78 32 2d 63 67 69 20 2d 3e 20  ext/ocx2-cgi -> 
7ea0: 72 6f 6f 74 2f 63 75 72 72 65 6e 74 2f 6f 63 78  root/current/ocx
7eb0: 32 2c 20 65 78 74 2f 6f 63 78 32 2d 63 67 69 2d  2, ext/ocx2-cgi-
7ec0: 6e 65 78 74 20 2d 3e 20 72 6f 6f 74 2f 73 74 61  next -> root/sta
7ed0: 67 65 64 2f 6e 65 78 74 2f 6f 63 78 32 20 61 6e  ged/next/ocx2 an
7ee0: 64 20 62 69 6e 2f 6f 63 78 32 20 2d 3e 20 72 6f  d bin/ocx2 -> ro
7ef0: 6f 74 2f 63 75 72 72 65 6e 74 2f 6f 63 78 32 2e  ot/current/ocx2.
7f00: 20 54 68 69 73 20 69 73 20 74 68 65 20 6c 61 79   This is the lay
7f10: 6f 75 74 20 73 63 72 69 70 74 73 2f 73 74 61 72  out scripts/star
7f20: 74 2d 66 6f 73 73 69 6c 2e 63 72 20 6d 61 6b 65  t-fossil.cr make
7f30: 73 2e 20 49 74 20 69 73 20 61 20 63 6f 70 79 20  s. It is a copy 
7f40: 72 61 74 68 65 72 20 74 68 61 6e 20 61 20 6c 69  rather than a li
7f50: 6e 6b 20 74 6f 20 74 68 65 20 73 74 61 67 65 64  nk to the staged
7f60: 20 66 69 6c 65 20 6f 6e 20 70 75 72 70 6f 73 65   file on purpose
7f70: 3a 20 45 6e 74 72 79 2e 72 65 6c 65 61 73 65 64  : Entry.released
7f80: 5f 72 6f 6f 74 20 74 61 6b 65 73 20 74 68 65 20  _root takes the 
7f90: 70 61 72 65 6e 74 20 6f 66 20 73 74 61 67 65 64  parent of staged
7fa0: 2f 20 61 73 20 69 74 73 20 72 65 6c 65 61 73 65  / as its release
7fb0: 20 72 6f 6f 74 2c 20 73 6f 20 72 75 6e 6e 69 6e   root, so runnin
7fc0: 67 20 74 68 65 20 73 74 61 67 65 64 20 66 69 6c  g the staged fil
7fd0: 65 20 69 6e 20 70 6c 61 63 65 20 77 6f 75 6c 64  e in place would
7fe0: 20 6d 61 6b 65 20 74 68 65 20 72 65 61 6c 20 70   make the real p
7ff0: 72 6f 6a 65 63 74 20 64 69 72 65 63 74 6f 72 79  roject directory
8000: 20 69 74 73 20 72 6f 6f 74 2c 20 61 6e 64 20 61   its root, and a
8010: 63 63 65 70 74 2c 20 72 6f 6c 6c 62 61 63 6b 20  ccept, rollback 
8020: 61 6e 64 20 68 6f 6f 6b 20 77 6f 75 6c 64 20 61  and hook would a
8030: 63 74 20 74 68 65 72 65 2e 20 73 74 61 74 75 73  ct there. status
8040: 20 63 6f 6e 66 69 72 6d 73 20 74 68 65 20 72 6f   confirms the ro
8050: 6f 74 20 69 73 20 44 49 52 2f 72 6f 6f 74 2e 5c  ot is DIR/root.\
8060: 6e 2d 20 2a 2a 65 78 74 2f 77 68 6f 3a 2a 2a 20  n- **ext/who:** 
8070: 74 68 65 20 73 61 6d 65 20 76 69 65 77 65 72 20  the same viewer 
8080: 73 63 72 69 70 74 20 73 65 72 76 65 64 5f 6e 6f  script served_no
8090: 64 65 2e 63 72 20 77 72 69 74 65 73 2e 20 46 6f  de.cr writes. Fo
80a0: 73 73 69 6c 20 32 2e 32 37 20 77 72 61 70 73 20  ssil 2.27 wraps 
80b0: 69 74 73 20 74 65 78 74 2f 70 6c 61 69 6e 20 6f  its text/plain o
80c0: 75 74 70 75 74 20 69 6e 20 74 68 65 20 73 6b 69  utput in the ski
80d0: 6e 2e 20 46 6f 72 20 6e 6f 62 6f 64 79 20 69 74  n. For nobody it
80e0: 20 73 68 6f 77 73 20 5c 22 76 69 65 77 65 72 3d   shows \"viewer=
80f0: 5c 22 20 77 69 74 68 20 6e 6f 74 68 69 6e 67 20  \" with nothing 
8100: 61 66 74 65 72 20 69 74 2e 5c 6e 2d 20 2a 2a 54  after it.\n- **T
8110: 68 65 20 72 65 70 6f 73 69 74 6f 72 79 3a 2a 2a  he repository:**
8120: 20 44 49 52 2f 73 65 72 76 65 72 2f 72 65 70 6f   DIR/server/repo
8130: 2e 66 6f 73 73 69 6c 2c 20 6d 61 64 65 20 77 69  .fossil, made wi
8140: 74 68 20 5c 22 66 6f 73 73 69 6c 20 6e 65 77 20  th \"fossil new 
8150: 2d 41 20 6f 77 6e 65 72 5c 22 2c 20 77 69 74 68  -A owner\", with
8160: 20 61 20 73 65 72 76 65 72 2d 73 69 64 65 20 63   a server-side c
8170: 68 65 63 6b 6f 75 74 20 61 74 20 44 49 52 2f 73  heckout at DIR/s
8180: 65 72 76 65 72 2f 63 68 65 63 6b 6f 75 74 2e 5c  erver/checkout.\
8190: 6e 2d 20 2a 2a 55 73 65 72 73 3a 2a 2a 20 6f 77  n- **Users:** ow
81a0: 6e 65 72 20 28 73 29 2c 20 73 61 6c 6c 79 20 28  ner (s), sally (
81b0: 73 29 2c 20 61 64 61 6d 20 28 61 29 2c 20 69 76  s), adam (a), iv
81c0: 79 20 28 69 6f 29 2c 20 6f 74 74 6f 20 28 6f 29  y (io), otto (o)
81d0: 2c 20 72 69 74 61 20 28 52 69 29 2e 20 6e 6f 62  , rita (Ri). nob
81e0: 6f 64 79 20 28 67 6a 6f 72 7a 29 2c 20 61 6e 6f  ody (gjorz), ano
81f0: 6e 79 6d 6f 75 73 20 28 68 7a 29 20 61 6e 64 20  nymous (hz) and 
8200: 46 6f 73 73 69 6c 27 73 20 6f 77 6e 20 64 65 76  Fossil's own dev
8210: 65 6c 6f 70 65 72 20 61 6e 64 20 72 65 61 64 65  eloper and reade
8220: 72 20 75 73 65 72 73 20 61 72 65 20 6c 65 66 74  r users are left
8230: 20 61 73 20 5c 22 66 6f 73 73 69 6c 20 6e 65 77   as \"fossil new
8240: 5c 22 20 6d 61 6b 65 73 20 74 68 65 6d 2e 5c 6e  \" makes them.\n
8250: 2d 20 2a 2a 43 68 65 63 6b 2d 69 6e 73 3a 2a 2a  - **Check-ins:**
8260: 20 66 6f 75 72 2c 20 62 79 20 6f 77 6e 65 72 2c   four, by owner,
8270: 20 69 76 79 2c 20 73 61 6c 6c 79 20 61 6e 64 20   ivy, sally and 
8280: 69 76 79 2c 20 61 66 74 65 72 20 46 6f 73 73 69  ivy, after Fossi
8290: 6c 27 73 20 69 6e 69 74 69 61 6c 20 63 68 65 63  l's initial chec
82a0: 6b 2d 69 6e 2e 5c 6e 2d 20 2a 2a 57 69 6b 69 20  k-in.\n- **Wiki 
82b0: 70 61 67 65 3a 2a 2a 20 5c 22 4e 6f 74 65 73 5c  page:** \"Notes\
82c0: 22 2c 20 4d 61 72 6b 64 6f 77 6e 2c 20 77 72 69  ", Markdown, wri
82d0: 74 74 65 6e 20 62 79 20 61 64 61 6d 2e 5c 6e 2d  tten by adam.\n-
82e0: 20 2a 2a 54 69 63 6b 65 74 3a 2a 2a 20 6d 61 64   **Ticket:** mad
82f0: 65 20 62 79 20 6f 77 6e 65 72 2c 20 74 68 65 6e  e by owner, then
8300: 20 63 68 61 6e 67 65 64 20 62 79 20 69 76 79 20   changed by ivy 
8310: 61 6e 64 20 62 79 20 73 61 6c 6c 79 20 28 73 74  and by sally (st
8320: 61 74 75 73 20 46 69 78 65 64 29 2e 5c 6e 2d 20  atus Fixed).\n- 
8330: 2a 2a 46 6f 72 75 6d 20 74 68 72 65 61 64 3a 2a  **Forum thread:*
8340: 2a 20 70 6f 73 74 65 64 20 74 68 72 6f 75 67 68  * posted through
8350: 20 46 6f 73 73 69 6c 27 73 20 6f 77 6e 20 2f 66   Fossil's own /f
8360: 6f 72 75 6d 65 31 20 61 6e 64 20 2f 66 6f 72 75  orume1 and /foru
8370: 6d 65 32 20 66 6f 72 6d 73 2e 20 6f 77 6e 65 72  me2 forms. owner
8380: 27 73 20 66 69 72 73 74 20 70 6f 73 74 2c 20 61  's first post, a
8390: 20 72 65 70 6c 79 20 62 79 20 61 64 61 6d 2c 20   reply by adam, 
83a0: 73 61 6c 6c 79 27 73 20 72 65 70 6c 79 20 74 6f  sally's reply to
83b0: 20 61 64 61 6d 2c 20 61 6e 64 20 61 20 73 65 63   adam, and a sec
83c0: 6f 6e 64 20 72 65 70 6c 79 20 74 6f 20 74 68 65  ond reply to the
83d0: 20 66 69 72 73 74 20 70 6f 73 74 20 62 79 20 6f   first post by o
83e0: 77 6e 65 72 2e 5c 6e 2d 20 2a 2a 54 68 65 20 73  wner.\n- **The s
83f0: 65 72 76 65 72 3a 2a 2a 20 5c 22 66 6f 73 73 69  erver:** \"fossi
8400: 6c 20 73 65 72 76 65 72 20 2d 2d 6c 6f 63 61 6c  l server --local
8410: 68 6f 73 74 20 2d 2d 70 6f 72 74 20 50 4f 52 54  host --port PORT
8420: 20 2d 2d 6e 6f 6a 61 69 6c 20 2d 2d 65 78 74 72   --nojail --extr
8430: 6f 6f 74 20 44 49 52 2f 65 78 74 5c 22 20 6f 6e  oot DIR/ext\" on
8440: 20 74 68 65 20 72 65 70 6f 73 69 74 6f 72 79 2c   the repository,
8450: 20 73 74 61 72 74 65 64 20 77 69 74 68 20 73 65   started with se
8460: 74 73 69 64 20 61 6e 64 20 6e 69 63 65 20 2d 6e  tsid and nice -n
8470: 20 31 30 2e 5c 6e 2d 20 2a 2a 69 76 79 27 73 20   10.\n- **ivy's 
8480: 63 6c 6f 6e 65 3a 2a 2a 20 6d 61 64 65 20 6f 76  clone:** made ov
8490: 65 72 20 48 54 54 50 20 61 73 20 69 76 79 20 77  er HTTP as ivy w
84a0: 69 74 68 20 2d 2d 73 61 76 65 2d 68 74 74 70 2d  ith --save-http-
84b0: 70 61 73 73 77 6f 72 64 2c 20 61 74 20 44 49 52  password, at DIR
84c0: 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 63 6c 6f 6e  /clones/ivy/clon
84d0: 65 2e 66 6f 73 73 69 6c 2c 20 77 69 74 68 20 61  e.fossil, with a
84e0: 75 74 6f 73 79 6e 63 20 6f 66 66 20 61 6e 64 20  utosync off and 
84f0: 61 20 63 68 65 63 6b 6f 75 74 20 61 74 20 44 49  a checkout at DI
8500: 52 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74 72 65  R/clones/ivy/tre
8510: 65 2e 20 49 74 73 20 72 65 6d 6f 74 65 20 69 73  e. Its remote is
8520: 20 68 74 74 70 3a 2f 2f 69 76 79 40 31 32 37 2e   http://ivy@127.
8530: 30 2e 30 2e 31 3a 50 4f 52 54 2f 2e 5c 6e 5c 6e  0.0.1:PORT/.\n\n
8540: 45 76 65 72 79 20 66 6f 73 73 69 6c 20 63 61 6c  Every fossil cal
8550: 6c 20 72 75 6e 73 20 77 69 74 68 20 6e 69 63 65  l runs with nice
8560: 20 61 6e 64 20 48 4f 4d 45 3d 44 49 52 2f 68 6f   and HOME=DIR/ho
8570: 6d 65 2c 20 73 6f 20 6e 6f 20 7e 2f 2e 66 6f 73  me, so no ~/.fos
8580: 73 69 6c 20 6f 75 74 73 69 64 65 20 44 49 52 20  sil outside DIR 
8590: 69 73 20 74 6f 75 63 68 65 64 2e 20 4f 6e 6c 79  is touched. Only
85a0: 20 74 68 65 20 73 65 72 76 65 72 27 73 20 6f 77   the server's ow
85b0: 6e 20 2d 52 20 72 65 61 64 73 20 77 65 72 65 20  n -R reads were 
85c0: 72 75 6e 20 6f 75 74 73 69 64 65 20 69 74 2e 5c  run outside it.\
85d0: 6e 5c 6e 46 69 6c 65 73 20 66 6f 72 20 74 65 73  n\nFiles for tes
85e0: 74 65 72 73 3a 5c 6e 2d 20 2a 2a 44 49 52 2f 70  ters:\n- **DIR/p
85f0: 61 73 73 77 6f 72 64 73 2e 74 78 74 20 28 6d 6f  asswords.txt (mo
8600: 64 65 20 36 30 30 29 3a 2a 2a 20 6f 6e 65 20 6c  de 600):** one l
8610: 69 6e 65 20 70 65 72 20 75 73 65 72 2c 20 5c 22  ine per user, \"
8620: 75 73 65 72 20 70 61 73 73 77 6f 72 64 20 63 61  user password ca
8630: 70 61 62 69 6c 69 74 69 65 73 5c 22 2e 20 6f 77  pabilities\". ow
8640: 6e 65 72 27 73 20 70 61 73 73 77 6f 72 64 20 69  ner's password i
8650: 73 20 74 68 65 20 6f 6e 65 20 5c 22 66 6f 73 73  s the one \"foss
8660: 69 6c 20 6e 65 77 5c 22 20 70 72 69 6e 74 65 64  il new\" printed
8670: 3b 20 74 68 65 20 6f 74 68 65 72 73 20 61 72 65  ; the others are
8680: 20 72 61 6e 64 6f 6d 20 68 65 78 20 73 63 72 61   random hex scra
8690: 74 63 68 20 70 61 73 73 77 6f 72 64 73 2e 5c 6e  tch passwords.\n
86a0: 2d 20 2a 2a 44 49 52 2f 66 61 63 74 73 2e 74 78  - **DIR/facts.tx
86b0: 74 3a 2a 2a 20 74 68 65 20 55 52 4c 2c 20 74 68  t:** the URL, th
86c0: 65 20 4f 43 58 20 70 61 67 65 2c 20 65 76 65 72  e OCX page, ever
86d0: 79 20 70 61 74 68 2c 20 65 61 63 68 20 63 68 65  y path, each che
86e0: 63 6b 2d 69 6e 20 68 61 73 68 20 77 69 74 68 20  ck-in hash with 
86f0: 69 74 73 20 75 73 65 72 2c 20 74 68 65 20 74 68  its user, the th
8700: 72 65 61 64 20 61 6e 64 20 72 65 70 6c 79 20 68  read and reply h
8710: 61 73 68 65 73 2c 20 74 68 65 20 74 69 63 6b 65  ashes, the ticke
8720: 74 20 68 61 73 68 2c 20 74 68 65 20 77 69 6b 69  t hash, the wiki
8730: 20 70 61 67 65 20 6e 61 6d 65 2c 20 61 6e 64 20   page name, and 
8740: 74 68 65 20 63 61 70 61 62 69 6c 69 74 69 65 73  the capabilities
8750: 20 6f 66 20 6e 6f 62 6f 64 79 20 61 6e 64 20 61   of nobody and a
8760: 6e 6f 6e 79 6d 6f 75 73 2e 5c 6e 2d 20 2a 2a 44  nonymous.\n- **D
8770: 49 52 2f 65 6e 76 2e 73 68 3a 2a 2a 20 5c 22 2e  IR/env.sh:** \".
8780: 20 44 49 52 2f 65 6e 76 2e 73 68 5c 22 20 73 65   DIR/env.sh\" se
8790: 74 73 20 48 4f 4d 45 3d 44 49 52 2f 68 6f 6d 65  ts HOME=DIR/home
87a0: 2c 20 70 75 74 73 20 44 49 52 2f 62 69 6e 20 28  , puts DIR/bin (
87b0: 6f 63 78 32 29 20 66 69 72 73 74 20 6f 6e 20 50  ocx2) first on P
87c0: 41 54 48 2c 20 61 6e 64 20 73 65 74 73 20 55 52  ATH, and sets UR
87d0: 4c 20 61 6e 64 20 52 45 50 4f 2e 5c 6e 2d 20 2a  L and REPO.\n- *
87e0: 2a 4c 6f 67 73 3a 2a 2a 20 44 49 52 2f 73 65 72  *Logs:** DIR/ser
87f0: 76 65 72 2e 6c 6f 67 20 61 6e 64 20 44 49 52 2f  ver.log and DIR/
8800: 73 65 72 76 65 72 2e 65 72 72 2e 6c 6f 67 2e 5c  server.err.log.\
8810: 6e 5c 6e 53 74 6f 70 20 61 6e 64 20 72 65 73 74  n\nStop and rest
8820: 61 72 74 3a 5c 6e 2d 20 44 49 52 2f 73 74 6f 70  art:\n- DIR/stop
8830: 2e 73 68 20 73 74 6f 70 73 20 74 68 65 20 73 65  .sh stops the se
8840: 72 76 65 72 27 73 20 70 72 6f 63 65 73 73 20 67  rver's process g
8850: 72 6f 75 70 2c 20 74 68 65 6e 20 65 6e 64 73 20  roup, then ends 
8860: 61 6e 79 20 70 72 6f 63 65 73 73 20 73 74 69 6c  any process stil
8870: 6c 20 73 65 72 76 69 6e 67 20 74 68 61 74 20 72  l serving that r
8880: 65 70 6f 73 69 74 6f 72 79 2e 20 54 68 69 73 20  epository. This 
8890: 73 65 63 6f 6e 64 20 73 74 65 70 20 69 73 20 6e  second step is n
88a0: 65 65 64 65 64 3a 20 46 6f 73 73 69 6c 27 73 20  eeded: Fossil's 
88b0: 62 61 63 6b 6f 66 66 69 63 65 20 70 72 6f 63 65  backoffice proce
88c0: 73 73 20 6c 65 61 76 65 73 20 74 68 65 20 73 65  ss leaves the se
88d0: 72 76 65 72 27 73 20 70 72 6f 63 65 73 73 20 67  rver's process g
88e0: 72 6f 75 70 20 61 6e 64 20 73 75 72 76 69 76 65  roup and survive
88f0: 64 20 61 20 70 6c 61 69 6e 20 67 72 6f 75 70 20  d a plain group 
8900: 6b 69 6c 6c 20 69 6e 20 6d 79 20 66 69 72 73 74  kill in my first
8910: 20 72 75 6e 2e 20 73 74 6f 70 2e 73 68 20 70 72   run. stop.sh pr
8920: 69 6e 74 73 20 5c 22 73 74 6f 70 70 65 64 3a 20  ints \"stopped: 
8930: 6e 6f 74 68 69 6e 67 20 73 65 72 76 65 73 20 52  nothing serves R
8940: 45 50 4f 5c 22 2c 20 6f 72 20 65 78 69 74 73 20  EPO\", or exits 
8950: 31 20 69 66 20 73 6f 6d 65 74 68 69 6e 67 20 73  1 if something s
8960: 74 69 6c 6c 20 64 6f 65 73 2e 5c 6e 2d 20 44 49  till does.\n- DI
8970: 52 2f 73 74 61 72 74 2e 73 68 20 73 74 61 72 74  R/start.sh start
8980: 73 20 69 74 20 61 67 61 69 6e 20 6f 6e 20 74 68  s it again on th
8990: 65 20 73 61 6d 65 20 70 6f 72 74 20 61 6e 64 20  e same port and 
89a0: 77 61 69 74 73 20 75 6e 74 69 6c 20 69 74 20 61  waits until it a
89b0: 6e 73 77 65 72 73 2e 5c 6e 2d 20 49 66 20 73 65  nswers.\n- If se
89c0: 74 75 70 20 66 61 69 6c 73 20 61 66 74 65 72 20  tup fails after 
89d0: 74 68 65 20 73 65 72 76 65 72 20 68 61 73 20 73  the server has s
89e0: 74 61 72 74 65 64 2c 20 61 6e 20 45 58 49 54 20  tarted, an EXIT 
89f0: 74 72 61 70 20 72 75 6e 73 20 73 74 6f 70 2e 73  trap runs stop.s
8a00: 68 2e 20 49 20 68 61 76 65 20 6e 6f 74 20 74 72  h. I have not tr
8a10: 69 65 64 20 74 68 61 74 20 66 61 69 6c 75 72 65  ied that failure
8a20: 20 70 61 74 68 2e 5c 6e 5c 6e 4c 65 66 74 20 66   path.\n\nLeft f
8a30: 6f 72 20 74 65 73 74 65 72 73 3a 20 61 20 73 74  or testers: a st
8a40: 6f 70 70 65 64 20 65 6e 76 69 72 6f 6e 6d 65 6e  opped environmen
8a50: 74 20 61 74 20 2f 74 6d 70 2f 63 6c 61 75 64 65  t at /tmp/claude
8a60: 2d 30 2f 2d 76 61 72 2d 6c 69 62 2d 6f 63 78 2d  -0/-var-lib-ocx-
8a70: 61 67 65 6e 74 73 2d 6f 70 75 73 2d 6f 63 78 32  agents-opus-ocx2
8a80: 2d 70 72 6f 6a 65 63 74 73 2d 6f 6c 6c 61 6d 61  -projects-ollama
8a90: 2d 62 32 64 65 38 62 30 63 32 63 36 37 30 30 65  -b2de8b0c2c6700e
8aa0: 62 35 63 36 38 36 62 31 37 34 37 62 35 61 61 61  b5c686b1747b5aaa
8ab0: 31 65 32 64 32 64 30 31 33 37 30 61 63 35 35 66  1e2d2d01370ac55f
8ac0: 32 65 35 61 31 35 31 61 36 37 65 30 33 62 34 38  2e5a151a67e03b48
8ad0: 61 2f 33 66 37 63 66 65 32 35 2d 32 38 61 61 2d  a/3f7cfe25-28aa-
8ae0: 34 63 35 35 2d 38 32 37 63 2d 62 63 30 36 31 38  4c55-827c-bc0618
8af0: 64 61 38 31 65 36 2f 73 63 72 61 74 63 68 70 61  da81e6/scratchpa
8b00: 64 2f 61 64 76 65 72 73 61 72 79 2f 64 65 6d 6f  d/adversary/demo
8b10: 2c 20 6f 6e 20 70 6f 72 74 20 35 38 35 30 37 2e  , on port 58507.
8b20: 20 42 72 69 6e 67 20 69 74 20 62 61 63 6b 20 77   Bring it back w
8b30: 69 74 68 20 64 65 6d 6f 2f 73 74 61 72 74 2e 73  ith demo/start.s
8b40: 68 2e 22 2c 0a 20 22 76 65 72 69 66 69 65 64 22  h.",. "verified"
8b50: 3a 20 22 41 6c 6c 20 63 68 65 63 6b 73 20 61 72  : "All checks ar
8b60: 65 20 66 72 6f 6d 20 74 68 65 20 66 69 6e 61 6c  e from the final
8b70: 20 66 72 65 73 68 20 72 75 6e 3a 20 73 65 74 75   fresh run: setu
8b80: 70 2e 73 68 20 2e 2e 2e 2f 61 64 76 65 72 73 61  p.sh .../adversa
8b90: 72 79 2f 64 65 6d 6f 20 35 38 35 30 37 2c 20 77  ry/demo 58507, w
8ba0: 68 69 63 68 20 65 78 69 74 65 64 20 30 2e 20 45  hich exited 0. E
8bb0: 61 72 6c 69 65 72 20 74 72 69 61 6c 20 64 69 72  arlier trial dir
8bc0: 65 63 74 6f 72 69 65 73 20 77 65 72 65 20 72 65  ectories were re
8bd0: 6d 6f 76 65 64 2e 5c 6e 5c 6e 31 2e 20 60 63 75  moved.\n\n1. `cu
8be0: 72 6c 20 2d 73 20 5c 22 68 74 74 70 3a 2f 2f 31  rl -s \"http://1
8bf0: 32 37 2e 30 2e 30 2e 31 3a 35 38 35 30 37 2f 65  27.0.0.1:58507/e
8c00: 78 74 2f 6f 63 78 32 2d 63 67 69 2f 73 74 61 74  xt/ocx2-cgi/stat
8c10: 75 73 3f 6a 73 6f 6e 3d 6f 6e 5c 22 60 20 72 65  us?json=on\"` re
8c20: 74 75 72 6e 65 64 20 48 54 54 50 20 32 30 30 20  turned HTTP 200 
8c30: 77 69 74 68 20 4a 53 4f 4e 20 7b 5c 22 6f 6b 5c  with JSON {\"ok\
8c40: 22 3a 74 72 75 65 2c 5c 22 74 6f 6f 6c 5c 22 3a  ":true,\"tool\":
8c50: 5c 22 73 74 61 74 75 73 5c 22 2c 2e 2e 2e 7d 2e  \"status\",...}.
8c60: 20 73 74 6f 70 70 65 64 20 77 61 73 20 61 62 73   stopped was abs
8c70: 65 6e 74 3b 20 72 65 73 75 6c 74 2e 63 6f 6e 74  ent; result.cont
8c80: 65 78 74 2e 6c 6f 67 69 6e 20 77 61 73 20 5c 22  ext.login was \"
8c90: 6e 6f 62 6f 64 79 5c 22 20 77 69 74 68 20 63 61  nobody\" with ca
8ca0: 70 61 62 69 6c 69 74 69 65 73 20 5c 22 67 68 6a  pabilities \"ghj
8cb0: 6f 72 7a 5c 22 3b 20 72 65 73 75 6c 74 2e 72 65  orz\"; result.re
8cc0: 6c 65 61 73 65 20 77 61 73 20 5c 22 63 75 72 72  lease was \"curr
8cd0: 65 6e 74 5c 22 3b 20 72 65 73 75 6c 74 2e 63 6f  ent\"; result.co
8ce0: 6e 74 65 78 74 2e 72 6f 6f 74 20 77 61 73 20 44  ntext.root was D
8cf0: 49 52 2f 72 6f 6f 74 2c 20 74 68 65 20 73 63 72  IR/root, the scr
8d00: 61 74 63 68 20 72 6f 6f 74 2e 5c 6e 32 2e 20 45  atch root.\n2. E
8d10: 61 72 6c 69 65 72 2c 20 6f 6e 20 74 68 65 20 73  arlier, on the s
8d20: 61 6d 65 20 73 63 72 69 70 74 2c 20 61 64 61 6d  ame script, adam
8d30: 20 77 61 73 20 73 69 67 6e 65 64 20 69 6e 20 77   was signed in w
8d40: 69 74 68 20 60 63 75 72 6c 20 2d 63 20 6a 61 72  ith `curl -c jar
8d50: 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63 6f 64   --data-urlencod
8d60: 65 20 75 3d 61 64 61 6d 20 2d 2d 64 61 74 61 2d  e u=adam --data-
8d70: 75 72 6c 65 6e 63 6f 64 65 20 70 3d 2e 2e 2e 20  urlencode p=... 
8d80: 2d 64 20 69 6e 3d 31 20 24 55 52 4c 2f 6c 6f 67  -d in=1 $URL/log
8d90: 69 6e 60 2e 20 54 68 65 6e 20 60 63 75 72 6c 20  in`. Then `curl 
8da0: 2d 62 20 6a 61 72 20 5c 22 24 55 52 4c 2f 65 78  -b jar \"$URL/ex
8db0: 74 2f 6f 63 78 32 2d 63 67 69 2f 73 74 61 74 75  t/ocx2-cgi/statu
8dc0: 73 3f 6a 73 6f 6e 3d 6f 6e 5c 22 60 20 72 65 74  s?json=on\"` ret
8dd0: 75 72 6e 65 64 20 48 54 54 50 20 32 30 30 20 77  urned HTTP 200 w
8de0: 69 74 68 20 6c 6f 67 69 6e 20 5c 22 61 64 61 6d  ith login \"adam
8df0: 5c 22 20 61 6e 64 20 63 61 70 61 62 69 6c 69 74  \" and capabilit
8e00: 69 65 73 20 5c 22 61 62 63 64 65 66 67 68 69 6a  ies \"abcdefghij
8e10: 6b 6c 6d 6e 6f 70 71 72 74 77 7a 32 33 34 35 36  klmnopqrtwz23456
8e20: 37 41 44 5c 22 2e 20 54 68 69 73 20 73 68 6f 77  7AD\". This show
8e30: 73 20 46 6f 73 73 69 6c 20 69 74 73 65 6c 66 20  s Fossil itself 
8e40: 73 69 67 6e 73 20 74 68 65 20 76 69 65 77 65 72  signs the viewer
8e50: 20 69 6e 20 61 6e 64 20 68 61 6e 64 73 20 74 68   in and hands th
8e60: 65 6d 20 74 6f 20 74 68 65 20 43 47 49 2e 5c 6e  em to the CGI.\n
8e70: 33 2e 20 60 28 63 64 20 44 49 52 2f 63 6c 6f 6e  3. `(cd DIR/clon
8e80: 65 73 2f 69 76 79 2f 74 72 65 65 20 26 26 20 6f  es/ivy/tree && o
8e90: 63 78 32 20 2d 2d 6a 73 6f 6e 20 72 65 63 65 69  cx2 --json recei
8ea0: 70 74 29 60 20 65 78 69 74 65 64 20 30 20 61 6e  pt)` exited 0 an
8eb0: 64 20 72 65 74 75 72 6e 65 64 20 7b 5c 22 6f 6b  d returned {\"ok
8ec0: 5c 22 3a 74 72 75 65 2c 5c 22 74 6f 6f 6c 5c 22  \":true,\"tool\"
8ed0: 3a 5c 22 72 65 63 65 69 70 74 5c 22 2c 2e 2e 2e  :\"receipt\",...
8ee0: 2c 5c 22 72 65 73 75 6c 74 5c 22 3a 7b 5c 22 61  ,\"result\":{\"a
8ef0: 72 74 69 66 61 63 74 73 5c 22 3a 5b 5d 2c 5c 22  rtifacts\":[],\"
8f00: 61 73 6b 65 64 5c 22 3a 5c 22 68 74 74 70 3a 2f  asked\":\"http:/
8f10: 2f 31 32 37 2e 30 2e 30 2e 31 3a 35 38 35 30 37  /127.0.0.1:58507
8f20: 2f 5c 22 7d 7d 2e 20 49 74 73 20 6c 6f 67 20 73  /\"}}. Its log s
8f30: 68 6f 77 73 20 72 65 61 64 5f 72 65 6d 6f 74 65  hows read_remote
8f40: 2c 20 74 68 65 6e 20 61 73 6b 5f 73 65 72 76 65  , then ask_serve
8f50: 72 5f 72 65 63 65 69 70 74 73 20 61 67 61 69 6e  r_receipts again
8f60: 73 74 20 74 68 65 20 73 65 72 76 65 72 2e 5c 6e  st the server.\n
8f70: 34 2e 20 4f 6e 20 74 68 65 20 65 61 72 6c 69 65  4. On the earlie
8f80: 72 20 72 75 6e 2c 20 60 6f 63 78 32 20 2d 2d 6a  r run, `ocx2 --j
8f90: 73 6f 6e 20 72 65 63 65 69 70 74 20 2d 2d 61 72  son receipt --ar
8fa0: 74 69 66 61 63 74 73 20 5c 22 3c 74 68 72 65 61  tifacts \"<threa
8fb0: 64 20 68 61 73 68 3e 20 3c 69 76 79 27 73 20 6c  d hash> <ivy's l
8fc0: 61 73 74 20 63 68 65 63 6b 2d 69 6e 3e 20 30 30  ast check-in> 00
8fd0: 30 30 5c 75 32 30 32 36 30 30 30 30 5c 22 20 2d  00\u20260000\" -
8fe0: 2d 63 61 70 61 62 69 6c 69 74 69 65 73 2d 6f 66  -capabilities-of
8ff0: 20 72 69 74 61 60 20 72 65 74 75 72 6e 65 64 3a   rita` returned:
9000: 5c 6e 20 20 20 2d 20 74 68 65 20 74 68 72 65 61  \n   - the threa
9010: 64 3a 20 73 65 6e 64 65 72 20 6f 77 6e 65 72 2c  d: sender owner,
9020: 20 63 61 70 61 62 69 6c 69 74 69 65 73 20 73 67   capabilities sg
9030: 6a 6f 72 7a 68 2c 20 72 65 63 65 69 70 74 20 31  jorzh, receipt 1
9040: 30 2c 20 72 69 64 20 31 34 3b 5c 6e 20 20 20 2d  0, rid 14;\n   -
9050: 20 74 68 65 20 63 68 65 63 6b 2d 69 6e 3a 20 73   the check-in: s
9060: 65 6e 64 65 72 20 69 76 79 2c 20 63 61 70 61 62  ender ivy, capab
9070: 69 6c 69 74 69 65 73 20 69 6f 67 6a 72 7a 68 2c  ilities iogjrzh,
9080: 20 72 65 63 65 69 70 74 20 35 2c 20 72 69 64 20   receipt 5, rid 
9090: 39 3b 5c 6e 20 20 20 2d 20 74 68 65 20 7a 65 72  9;\n   - the zer
90a0: 6f 20 68 61 73 68 3a 20 72 65 63 65 69 76 65 64  o hash: received
90b0: 20 66 61 6c 73 65 3b 5c 6e 20 20 20 2d 20 72 69   false;\n   - ri
90c0: 74 61 3a 20 63 61 70 61 62 69 6c 69 74 69 65 73  ta: capabilities
90d0: 20 52 69 67 6a 6f 72 7a 68 2e 5c 6e 35 2e 20 60   Rigjorzh.\n5. `
90e0: 66 6f 73 73 69 6c 20 73 79 6e 63 60 20 66 72 6f  fossil sync` fro
90f0: 6d 20 69 76 79 27 73 20 63 68 65 63 6b 6f 75 74  m ivy's checkout
9100: 20 77 6f 72 6b 65 64 20 77 69 74 68 20 74 68 65   worked with the
9110: 20 73 61 76 65 64 20 70 61 73 73 77 6f 72 64 3a   saved password:
9120: 20 5c 22 52 6f 75 6e 64 2d 74 72 69 70 73 3a 20   \"Round-trips: 
9130: 31 20 41 72 74 69 66 61 63 74 73 20 73 65 6e 74  1 Artifacts sent
9140: 3a 20 30 20 72 65 63 65 69 76 65 64 3a 20 30 5c  : 0 received: 0\
9150: 22 2e 5c 6e 36 2e 20 54 68 65 20 72 65 70 6f 73  ".\n6. The repos
9160: 69 74 6f 72 79 20 68 6f 6c 64 73 20 77 68 61 74  itory holds what
9170: 20 74 68 65 20 73 63 72 69 70 74 20 63 6c 61 69   the script clai
9180: 6d 73 2c 20 72 65 61 64 20 77 69 74 68 20 66 6f  ms, read with fo
9190: 73 73 69 6c 20 73 71 6c 3a 20 74 68 65 20 75 73  ssil sql: the us
91a0: 65 72 20 74 61 62 6c 65 20 28 6c 6f 67 69 6e 2c  er table (login,
91b0: 20 63 61 70 29 20 69 73 20 61 73 20 6c 69 73 74   cap) is as list
91c0: 65 64 20 69 6e 20 74 68 65 20 75 73 61 67 65 20  ed in the usage 
91d0: 6e 6f 74 65 73 3b 20 74 68 65 72 65 20 61 72 65  notes; there are
91e0: 20 34 20 66 6f 72 75 6d 20 70 6f 73 74 73 20 28   4 forum posts (
91f0: 6f 77 6e 65 72 3b 20 61 64 61 6d 20 72 65 70 6c  owner; adam repl
9200: 79 69 6e 67 20 74 6f 20 74 68 65 20 66 69 72 73  ying to the firs
9210: 74 20 70 6f 73 74 3b 20 73 61 6c 6c 79 20 72 65  t post; sally re
9220: 70 6c 79 69 6e 67 20 74 6f 20 61 64 61 6d 3b 20  plying to adam; 
9230: 6f 77 6e 65 72 20 72 65 70 6c 79 69 6e 67 20 74  owner replying t
9240: 6f 20 74 68 65 20 66 69 72 73 74 20 70 6f 73 74  o the first post
9250: 29 3b 20 61 6e 64 20 74 68 65 20 65 76 65 6e 74  ); and the event
9260: 73 20 61 72 65 20 35 20 63 68 65 63 6b 2d 69 6e  s are 5 check-in
9270: 73 2c 20 77 69 6b 69 20 5c 22 2b 4e 6f 74 65 73  s, wiki \"+Notes
9280: 5c 22 20 62 79 20 61 64 61 6d 2c 20 61 6e 64 20  \" by adam, and 
9290: 74 69 63 6b 65 74 20 63 68 61 6e 67 65 73 20 62  ticket changes b
92a0: 79 20 6f 77 6e 65 72 2c 20 69 76 79 20 61 6e 64  y owner, ivy and
92b0: 20 73 61 6c 6c 79 2e 5c 6e 37 2e 20 53 74 6f 70   sally.\n7. Stop
92c0: 20 61 6e 64 20 72 65 73 74 61 72 74 3a 20 73 74   and restart: st
92d0: 6f 70 2e 73 68 20 70 72 69 6e 74 65 64 20 5c 22  op.sh printed \"
92e0: 73 74 6f 70 70 65 64 3a 20 6e 6f 74 68 69 6e 67  stopped: nothing
92f0: 20 73 65 72 76 65 73 20 5c 75 32 30 32 36 2f 64   serves \u2026/d
9300: 65 6d 6f 2f 73 65 72 76 65 72 2f 72 65 70 6f 2e  emo/server/repo.
9310: 66 6f 73 73 69 6c 5c 22 3b 20 73 74 61 72 74 2e  fossil\"; start.
9320: 73 68 20 70 72 69 6e 74 65 64 20 5c 22 73 65 72  sh printed \"ser
9330: 76 69 6e 67 20 68 74 74 70 3a 2f 2f 31 32 37 2e  ving http://127.
9340: 30 2e 30 2e 31 3a 35 38 35 30 37 5c 22 3b 20 73  0.0.1:58507\"; s
9350: 74 61 74 75 73 20 61 6e 73 77 65 72 65 64 20 32  tatus answered 2
9360: 30 30 20 61 67 61 69 6e 3b 20 73 74 6f 70 2e 73  00 again; stop.s
9370: 68 20 61 67 61 69 6e 2e 20 41 66 74 65 72 20 74  h again. After t
9380: 68 61 74 2c 20 60 70 73 60 20 73 68 6f 77 65 64  hat, `ps` showed
9390: 20 6e 6f 20 66 6f 73 73 69 6c 20 73 65 72 76 65   no fossil serve
93a0: 72 20 66 6f 72 20 61 6e 79 20 72 65 70 6f 73 69  r for any reposi
93b0: 74 6f 72 79 20 75 6e 64 65 72 20 61 64 76 65 72  tory under adver
93c0: 73 61 72 79 2f 2c 20 61 6e 64 20 60 63 75 72 6c  sary/, and `curl
93d0: 20 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e   http://127.0.0.
93e0: 31 3a 35 38 35 30 37 2f 60 20 65 78 69 74 65 64  1:58507/` exited
93f0: 20 37 20 28 63 6f 6e 6e 65 63 74 69 6f 6e 20 72   7 (connection r
9400: 65 66 75 73 65 64 29 2e 20 4e 6f 20 73 65 72 76  efused). No serv
9410: 65 72 20 49 20 73 74 61 72 74 65 64 20 69 73 20  er I started is 
9420: 73 74 69 6c 6c 20 72 75 6e 6e 69 6e 67 2e 5c 6e  still running.\n
9430: 38 2e 20 60 73 68 20 2d 6e 60 20 70 61 73 73 65  8. `sh -n` passe
9440: 73 20 6f 6e 20 73 65 74 75 70 2e 73 68 20 61 6e  s on setup.sh an
9450: 64 20 6f 6e 20 74 68 65 20 67 65 6e 65 72 61 74  d on the generat
9460: 65 64 20 73 74 61 72 74 2e 73 68 20 61 6e 64 20  ed start.sh and 
9470: 73 74 6f 70 2e 73 68 2e 5c 6e 5c 6e 4e 6f 74 20  stop.sh.\n\nNot 
9480: 64 6f 6e 65 3a 20 6e 6f 74 68 69 6e 67 20 77 61  done: nothing wa
9490: 73 20 63 6f 6d 6d 69 74 74 65 64 2c 20 73 79 6e  s committed, syn
94a0: 63 65 64 20 74 6f 20 61 20 72 65 61 6c 20 73 65  ced to a real se
94b0: 72 76 65 72 2c 20 70 6f 73 74 65 64 2c 20 73 74  rver, posted, st
94c0: 61 67 65 64 20 6f 72 20 61 63 63 65 70 74 65 64  aged or accepted
94d0: 2e 20 4e 6f 20 72 65 71 75 65 73 74 20 77 65 6e  . No request wen
94e0: 74 20 74 6f 20 61 6e 79 20 68 6f 73 74 20 62 75  t to any host bu
94f0: 74 20 31 32 37 2e 30 2e 30 2e 31 2e 20 54 68 65  t 127.0.0.1. The
9500: 20 74 72 65 65 2c 20 69 74 73 20 63 6c 6f 6e 65   tree, its clone
9510: 20 61 6e 64 20 73 74 61 67 65 64 2f 6e 65 78 74   and staged/next
9520: 20 77 65 72 65 20 6f 6e 6c 79 20 72 65 61 64 3a   were only read:
9530: 20 74 68 65 20 73 74 61 67 65 64 20 70 72 6f 67   the staged prog
9540: 72 61 6d 20 77 61 73 20 63 6f 70 69 65 64 20 77  ram was copied w
9550: 69 74 68 20 63 70 20 61 6e 64 20 6e 65 76 65 72  ith cp and never
9560: 20 72 75 6e 20 66 72 6f 6d 20 69 74 73 20 6f 77   run from its ow
9570: 6e 20 70 6c 61 63 65 2e 22 0a 7d 00 00 00 00 00  n place.".}.....
9580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9590: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
95f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9600: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
9610: 2f 61 74 74 61 63 6b 2d 63 6f 6e 63 75 72 72 65  /attack-concurre
9620: 6e 63 79 2e 6a 73 6f 6e 00 00 00 00 00 00 00 00  ncy.json........
9630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9650: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9660: 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
9670: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
9680: 30 30 34 34 36 35 33 00 31 35 32 36 35 32 30 34  0044653.15265204
9690: 31 36 34 00 30 31 37 35 34 33 00 20 30 00 00 00  164.017543. 0...
96a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
96b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
96c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
96d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
96e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
96f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9700: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
9710: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9720: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
9730: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9740: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9750: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9760: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9770: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9790: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
97f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
9800: 7b 0a 20 22 66 69 6e 64 69 6e 67 73 22 3a 20 5b  {. "findings": [
9810: 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a  .  {.   "title":
9820: 20 22 41 20 66 6f 72 75 6d 20 77 72 69 74 65 20   "A forum write 
9830: 6f 6e 20 74 68 65 20 73 65 72 76 65 64 20 72 65  on the served re
9840: 70 6f 73 69 74 6f 72 79 20 28 63 72 65 61 74 65  pository (create
9850: 2c 20 73 74 6f 70 2c 20 61 20 6e 6f 64 65 27 73  , stop, a node's
9860: 20 72 65 70 6f 72 74 29 20 63 61 6e 20 62 65 20   report) can be 
9870: 6c 65 66 74 20 68 61 6c 66 2d 77 72 69 74 74 65  left half-writte
9880: 6e 3a 20 74 68 65 20 61 72 74 69 66 61 63 74 20  n: the artifact 
9890: 69 73 20 73 74 6f 72 65 64 20 62 75 74 20 6e 65  is stored but ne
98a0: 76 65 72 20 69 6e 64 65 78 65 64 20 6f 6e 20 74  ver indexed on t
98b0: 68 65 20 73 65 72 76 65 72 2c 20 74 68 65 20 61  he server, the a
98c0: 6e 73 77 65 72 20 67 69 76 65 73 20 6e 6f 20 68  nswer gives no h
98d0: 61 73 68 2c 20 61 6e 64 20 63 6c 6f 6e 65 73 20  ash, and clones 
98e0: 61 6e 64 20 6e 6f 64 65 73 20 73 74 69 6c 6c 20  and nodes still 
98f0: 61 63 74 20 6f 6e 20 69 74 22 2c 0a 20 20 20 22  act on it",.   "
9900: 73 65 76 65 72 69 74 79 22 3a 20 22 68 69 67 68  severity": "high
9910: 22 2c 0a 20 20 20 22 72 65 70 72 6f 64 75 63 74  ",.   "reproduct
9920: 69 6f 6e 22 3a 20 22 44 3d 2f 74 6d 70 2f 63 6c  ion": "D=/tmp/cl
9930: 61 75 64 65 2d 30 2f 2d 76 61 72 2d 6c 69 62 2d  aude-0/-var-lib-
9940: 6f 63 78 2d 61 67 65 6e 74 73 2d 6f 70 75 73 2d  ocx-agents-opus-
9950: 6f 63 78 32 2d 70 72 6f 6a 65 63 74 73 2d 6f 6c  ocx2-projects-ol
9960: 6c 61 6d 61 2d 62 32 64 65 38 62 30 63 32 63 36  lama-b2de8b0c2c6
9970: 37 30 30 65 62 35 63 36 38 36 62 31 37 34 37 62  700eb5c686b1747b
9980: 35 61 61 61 31 65 32 64 32 64 30 31 33 37 30 61  5aaa1e2d2d01370a
9990: 63 35 35 66 32 65 35 61 31 35 31 61 36 37 65 30  c55f2e5a151a67e0
99a0: 33 62 34 38 61 2f 33 66 37 63 66 65 32 35 2d 32  3b48a/3f7cfe25-2
99b0: 38 61 61 2d 34 63 35 35 2d 38 32 37 63 2d 62 63  8aa-4c55-827c-bc
99c0: 30 36 31 38 64 61 38 31 65 36 2f 73 63 72 61 74  0618da81e6/scrat
99d0: 63 68 70 61 64 2f 61 64 76 65 72 73 61 72 79 2f  chpad/adversary/
99e0: 63 6f 6e 63 75 72 72 65 6e 63 79 3b 20 73 65 74  concurrency; set
99f0: 75 70 2e 73 68 20 24 44 20 31 38 39 33 34 3b 20  up.sh $D 18934; 
9a00: 2e 20 24 44 2f 65 6e 76 2e 73 68 2e 20 48 6f 77  . $D/env.sh. How
9a10: 20 74 68 65 20 6f 72 64 65 72 20 69 73 20 66 6f   the order is fo
9a20: 72 63 65 64 2c 20 77 69 74 68 20 6e 6f 20 73 6c  rced, with no sl
9a30: 65 65 70 73 3a 20 24 44 2f 73 68 69 6d 2f 66 6f  eeps: $D/shim/fo
9a40: 73 73 69 6c 20 69 73 20 70 75 74 20 66 69 72 73  ssil is put firs
9a50: 74 20 6f 6e 20 50 41 54 48 20 28 46 6f 73 73 69  t on PATH (Fossi
9a60: 6c 2e 65 6e 76 20 6b 65 65 70 73 20 74 68 65 20  l.env keeps the 
9a70: 64 69 72 65 63 74 6f 72 79 20 66 6f 73 73 69 6c  directory fossil
9a80: 20 77 61 73 20 66 6f 75 6e 64 20 69 6e 29 2e 20   was found in). 
9a90: 57 68 65 6e 20 74 68 65 20 66 69 66 6f 20 24 44  When the fifo $D
9aa0: 2f 63 74 6c 2f 67 61 74 65 2d 3c 63 6d 64 3e 20  /ctl/gate-<cmd> 
9ab0: 65 78 69 73 74 73 2c 20 74 68 65 20 73 68 69 6d  exists, the shim
9ac0: 20 77 72 69 74 65 73 20 69 74 73 20 70 69 64 20   writes its pid 
9ad0: 74 6f 20 74 68 65 20 66 69 66 6f 20 24 44 2f 63  to the fifo $D/c
9ae0: 74 6c 2f 61 72 72 69 76 65 2d 3c 63 6d 64 3e 20  tl/arrive-<cmd> 
9af0: 61 6e 64 20 62 6c 6f 63 6b 73 20 72 65 61 64 69  and blocks readi
9b00: 6e 67 20 74 68 65 20 67 61 74 65 2c 20 74 68 65  ng the gate, the
9b10: 6e 20 72 75 6e 73 20 65 78 65 63 20 2f 75 73 72  n runs exec /usr
9b20: 2f 62 69 6e 2f 66 6f 73 73 69 6c 2e 20 54 68 65  /bin/fossil. The
9b30: 20 6f 75 74 73 69 64 65 20 77 72 69 74 65 72 20   outside writer 
9b40: 69 73 20 74 68 65 20 73 71 6c 69 74 65 33 20 43  is the sqlite3 C
9b50: 4c 49 2c 20 66 65 64 20 74 68 72 6f 75 67 68 20  LI, fed through 
9b60: 61 20 66 69 66 6f 20 77 69 74 68 20 27 42 45 47  a fifo with 'BEG
9b70: 49 4e 20 49 4d 4d 45 44 49 41 54 45 3b 20 53 45  IN IMMEDIATE; SE
9b80: 4c 45 43 54 20 27 68 65 6c 64 27 3b 27 20 61 6e  LECT 'held';' an
9b90: 64 20 72 65 61 64 20 75 6e 74 69 6c 20 69 74 20  d read until it 
9ba0: 70 72 69 6e 74 73 20 27 68 65 6c 64 27 20 28 24  prints 'held' ($
9bb0: 44 2f 68 6f 6c 64 2e 73 68 29 2e 20 53 63 72 69  D/hold.sh). Scri
9bc0: 70 74 20 24 44 2f 74 4b 2e 73 68 3a 20 28 31 29  pt $D/tK.sh: (1)
9bd0: 20 24 44 2f 67 61 74 65 2e 73 68 20 61 72 6d 20   $D/gate.sh arm 
9be0: 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 2e 20  test-crosslink. 
9bf0: 28 32 29 20 49 6e 20 74 68 65 20 62 61 63 6b 67  (2) In the backg
9c00: 72 6f 75 6e 64 3a 20 50 41 54 48 3d 24 44 2f 73  round: PATH=$D/s
9c10: 68 69 6d 3a 24 50 41 54 48 20 6e 69 63 65 20 6f  him:$PATH nice o
9c20: 63 78 32 20 2d 2d 6a 73 6f 6e 20 2d 2d 72 65 70  cx2 --json --rep
9c30: 6f 73 69 74 6f 72 79 20 24 52 45 50 4f 20 2d 2d  ository $REPO --
9c40: 75 73 65 72 20 6f 77 6e 65 72 20 63 72 65 61 74  user owner creat
9c50: 65 20 5c 22 52 75 6e 20 4b 20 66 6f 72 20 6e 6f  e \"Run K for no
9c60: 64 65 61 2c 20 68 65 6c 64 20 62 65 66 6f 72 65  dea, held before
9c70: 20 63 72 6f 73 73 6c 69 6e 6b 2e 5c 22 20 2d 2d   crosslink.\" --
9c80: 6e 6f 64 65 20 6e 6f 64 65 61 20 2d 2d 66 69 65  node nodea --fie
9c90: 6c 64 73 20 27 7b 5c 22 70 72 6f 63 65 73 73 5c  lds '{\"process\
9ca0: 22 3a 7b 5c 22 75 73 65 72 5c 22 3a 5c 22 6f 74  ":{\"user\":\"ot
9cb0: 74 6f 5c 22 2c 5c 22 63 6f 6d 6d 61 6e 64 5c 22  to\",\"command\"
9cc0: 3a 5b 5c 22 74 72 75 65 5c 22 5d 7d 7d 27 2e 20  :[\"true\"]}}'. 
9cd0: 28 33 29 20 24 44 2f 67 61 74 65 2e 73 68 20 77  (3) $D/gate.sh w
9ce0: 61 69 74 20 74 65 73 74 2d 63 72 6f 73 73 6c 69  ait test-crossli
9cf0: 6e 6b 2e 20 28 34 29 20 73 71 6c 69 74 65 33 20  nk. (4) sqlite3 
9d00: 24 52 45 50 4f 20 74 61 6b 65 73 20 42 45 47 49  $REPO takes BEGI
9d10: 4e 20 49 4d 4d 45 44 49 41 54 45 2e 20 28 35 29  N IMMEDIATE. (5)
9d20: 20 24 44 2f 67 61 74 65 2e 73 68 20 6f 70 65 6e   $D/gate.sh open
9d30: 20 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 2c   test-crosslink,
9d40: 20 77 61 69 74 20 66 6f 72 20 74 68 65 20 63 72   wait for the cr
9d50: 65 61 74 65 20 74 6f 20 65 6e 64 2c 20 52 4f 4c  eate to end, ROL
9d60: 4c 42 41 43 4b 2e 20 28 36 29 20 73 71 6c 69 74  LBACK. (6) sqlit
9d70: 65 33 20 24 52 45 50 4f 20 5c 22 73 65 6c 65 63  e3 $REPO \"selec
9d80: 74 20 72 69 64 2c 75 75 69 64 2c 28 73 65 6c 65  t rid,uuid,(sele
9d90: 63 74 20 63 6f 75 6e 74 28 2a 29 20 66 72 6f 6d  ct count(*) from
9da0: 20 66 6f 72 75 6d 70 6f 73 74 20 66 20 77 68 65   forumpost f whe
9db0: 72 65 20 66 2e 66 70 69 64 3d 62 2e 72 69 64 29  re f.fpid=b.rid)
9dc0: 2c 28 73 65 6c 65 63 74 20 63 6f 75 6e 74 28 2a  ,(select count(*
9dd0: 29 20 66 72 6f 6d 20 65 76 65 6e 74 20 65 20 77  ) from event e w
9de0: 68 65 72 65 20 65 2e 6f 62 6a 69 64 3d 62 2e 72  here e.objid=b.r
9df0: 69 64 29 20 66 72 6f 6d 20 62 6c 6f 62 20 62 20  id) from blob b 
9e00: 77 68 65 72 65 20 72 69 64 3d 28 73 65 6c 65 63  where rid=(selec
9e10: 74 20 6d 61 78 28 72 69 64 29 20 66 72 6f 6d 20  t max(rid) from 
9e20: 62 6c 6f 62 29 5c 22 2e 20 28 37 29 20 63 64 20  blob)\". (7) cd 
9e30: 24 44 2f 6e 6f 64 65 3b 20 6e 69 63 65 20 6f 63  $D/node; nice oc
9e40: 78 32 20 2d 2d 6a 73 6f 6e 20 2d 2d 72 65 70 6f  x2 --json --repo
9e50: 73 69 74 6f 72 79 20 24 44 2f 6e 6f 64 65 2f 63  sitory $D/node/c
9e60: 6c 6f 6e 65 2e 66 6f 73 73 69 6c 20 70 6f 6c 6c  lone.fossil poll
9e70: 20 24 55 52 4c 20 24 44 2f 6e 6f 64 65 2f 6e 6f   $URL $D/node/no
9e80: 64 65 2e 6a 73 6f 6e 20 28 6e 6f 64 65 20 6e 6f  de.json (node no
9e90: 64 65 61 20 77 61 73 20 72 65 67 69 73 74 65 72  dea was register
9ea0: 65 64 20 77 69 74 68 20 70 6f 6c 6c 20 2d 2d 6c  ed with poll --l
9eb0: 6f 67 69 6e 20 6e 6f 64 65 61 20 61 6e 64 20 61  ogin nodea and a
9ec0: 70 70 72 6f 76 65 64 20 74 68 72 6f 75 67 68 20  pproved through 
9ed0: 50 4f 53 54 20 2f 65 78 74 2f 6f 63 78 32 2d 63  POST /ext/ocx2-c
9ee0: 67 69 2f 61 70 70 72 6f 76 65 20 61 73 20 6f 77  gi/approve as ow
9ef0: 6e 65 72 29 2e 20 28 38 29 20 6e 69 63 65 20 6f  ner). (8) nice o
9f00: 63 78 32 20 2d 2d 6a 73 6f 6e 20 2d 2d 72 65 70  cx2 --json --rep
9f10: 6f 73 69 74 6f 72 79 20 24 52 45 50 4f 20 2d 2d  ository $REPO --
9f20: 75 73 65 72 20 6f 77 6e 65 72 20 74 68 72 65 61  user owner threa
9f30: 64 20 61 33 37 32 39 33 65 66 2e 20 24 44 2f 74  d a37293ef. $D/t
9f40: 46 2e 73 68 20 69 73 20 74 68 65 20 73 61 6d 65  F.sh is the same
9f50: 20 77 69 74 68 20 2d 2d 6e 6f 64 65 20 6e 6f 64   with --node nod
9f60: 65 41 20 61 6e 64 20 6e 6f 20 70 6f 6c 6c 2e 20  eA and no poll. 
9f70: 41 66 74 65 72 20 69 74 2c 20 69 76 79 27 73 20  After it, ivy's 
9f80: 63 6c 6f 6e 65 20 72 61 6e 20 66 6f 73 73 69 6c  clone ran fossil
9f90: 20 70 75 6c 6c 2e 22 2c 0a 20 20 20 22 6f 62 73   pull.",.   "obs
9fa0: 65 72 76 65 64 22 3a 20 22 54 68 65 20 63 72 65  erved": "The cre
9fb0: 61 74 65 20 61 6e 73 77 65 72 65 64 20 6f 6b 3a  ate answered ok:
9fc0: 66 61 6c 73 65 20 77 69 74 68 20 6e 6f 20 72 65  false with no re
9fd0: 73 75 6c 74 2e 20 73 74 6f 70 70 65 64 20 77 61  sult. stopped wa
9fe0: 73 3a 20 5c 22 66 6f 73 73 69 6c 20 74 65 73 74  s: \"fossil test
9ff0: 2d 63 72 6f 73 73 6c 69 6e 6b 20 6f 6e 20 e2 80  -crosslink on â€
a000: a6 2f 73 65 72 76 65 72 2f 72 65 70 6f 2e 66 6f  ¦/server/repo.fo
a010: 73 73 69 6c 3a 20 61 20 77 72 69 74 65 72 20 6f  ssil: a writer o
a020: 75 74 73 69 64 65 20 4f 43 58 20 68 65 6c 64 20  utside OCX held 
a030: 74 68 65 20 72 65 70 6f 73 69 74 6f 72 79 2c 20  the repository, 
a040: 73 6f 20 74 68 69 73 20 63 6f 6d 6d 61 6e 64 20  so this command 
a050: 66 61 69 6c 65 64 3b 20 77 68 61 74 20 61 6e 20  failed; what an 
a060: 65 61 72 6c 69 65 72 20 63 6f 6d 6d 61 6e 64 20  earlier command 
a070: 77 72 6f 74 65 20 73 74 61 79 73 3a 20 44 61 74  wrote stays: Dat
a080: 61 62 61 73 65 20 65 72 72 6f 72 3a 20 64 61 74  abase error: dat
a090: 61 62 61 73 65 20 69 73 20 6c 6f 63 6b 65 64 3a  abase is locked:
a0a0: 20 7b 52 45 50 4c 41 43 45 20 49 4e 54 4f 20 66   {REPLACE INTO f
a0b0: 6f 72 75 6d 70 6f 73 74 28 2e 2e 2e 29 7d 3b 20  orumpost(...)}; 
a0c0: 61 6e 64 20 69 74 73 20 63 68 65 63 6b 6f 75 74  and its checkout
a0d0: 20 6f 66 20 e2 80 a6 2f 72 65 70 6f 2e 66 6f 73   of …/repo.fos
a0e0: 73 69 6c 20 77 61 73 20 6e 6f 74 20 63 6c 6f 73  sil was not clos
a0f0: 65 64 3a 20 66 6f 73 73 69 6c 20 63 6c 6f 73 65  ed: fossil close
a100: 20 e2 80 a6 3a 20 64 61 74 61 62 61 73 65 20 69   …: database i
a110: 73 20 6c 6f 63 6b 65 64 3a 20 7b 44 45 4c 45 54  s locked: {DELET
a120: 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48  E FROM config WH
a130: 45 52 45 20 6e 61 6d 65 3d 27 63 6b 6f 75 74 3a  ERE name='ckout:
a140: 2f 74 6d 70 2f 32 30 32 36 e2 80 a6 6f 63 78 2d  /tmp/2026…ocx-
a150: 63 68 65 63 6b 6f 75 74 2f 27 7d 5c 22 2e 20 54  checkout/'}\". T
a160: 68 65 20 68 61 73 68 20 69 73 20 6e 6f 74 20 6e  he hash is not n
a170: 61 6d 65 64 20 61 6e 79 77 68 65 72 65 20 69 6e  amed anywhere in
a180: 20 74 68 65 20 61 6e 73 77 65 72 2e 20 54 68 65   the answer. The
a190: 20 73 65 72 76 65 72 20 74 68 65 6e 20 68 65 6c   server then hel
a1a0: 64 20 72 69 64 20 35 36 20 3d 20 61 33 37 32 39  d rid 56 = a3729
a1b0: 33 65 66 61 30 37 36 35 35 32 37 31 39 39 62 36  3efa0765527199b6
a1c0: 32 39 33 37 63 33 37 66 38 63 39 61 31 66 65 37  2937c37f8c9a1fe7
a1d0: 34 62 35 61 38 64 36 61 64 33 61 33 36 66 36 30  4b5a8d6ad3a36f60
a1e0: 39 36 32 63 65 39 36 37 38 30 37 2c 20 77 69 74  962ce967807, wit
a1f0: 68 20 30 20 66 6f 72 75 6d 70 6f 73 74 20 72 6f  h 0 forumpost ro
a200: 77 73 20 61 6e 64 20 30 20 65 76 65 6e 74 20 72  ws and 0 event r
a210: 6f 77 73 2c 20 61 6e 64 20 69 74 20 73 74 61 79  ows, and it stay
a220: 73 20 74 68 61 74 20 77 61 79 3a 20 74 68 65 20  s that way: the 
a230: 73 65 72 76 65 72 20 6e 65 76 65 72 20 63 72 6f  server never cro
a240: 73 73 6c 69 6e 6b 73 20 69 74 20 61 67 61 69 6e  sslinks it again
a250: 2e 20 54 68 65 20 6e 6f 64 65 27 73 20 70 6f 6c  . The node's pol
a260: 6c 20 73 74 69 6c 6c 20 70 75 6c 6c 65 64 20 69  l still pulled i
a270: 74 20 28 61 72 74 69 66 61 63 74 73 20 5b 61 33  t (artifacts [a3
a280: 37 32 39 33 65 66 e2 80 a6 5d 29 20 61 6e 64 20  7293ef…]) and 
a290: 61 63 74 65 64 20 6f 6e 20 74 68 65 20 72 75 6e  acted on the run
a2a0: 20 61 6e 79 77 61 79 3a 20 61 6e 73 77 65 72 65   anyway: answere
a2b0: 64 20 5b 7b 72 75 6e 20 61 33 37 32 39 33 65 66  d [{run a37293ef
a2c0: e2 80 a6 2c 20 6f 75 74 63 6f 6d 65 20 72 65 66  …, outcome ref
a2d0: 75 73 65 64 2c 20 72 65 70 6f 72 74 20 36 63 66  used, report 6cf
a2e0: 63 37 62 38 62 e2 80 a6 7d 5d 2e 20 54 68 61 74  c7b8b…}]. That
a2f0: 20 72 65 70 6f 72 74 20 77 65 6e 74 20 74 6f 20   report went to 
a300: 74 68 65 20 73 65 72 76 65 72 20 61 6e 64 20 77  the server and w
a310: 61 73 20 69 6e 64 65 78 65 64 20 69 6e 74 6f 20  as indexed into 
a320: 74 68 72 65 61 64 20 72 6f 6f 74 20 72 69 64 20  thread root rid 
a330: 35 36 2c 20 61 20 72 65 70 6c 79 20 75 6e 64 65  56, a reply unde
a340: 72 20 61 20 66 69 72 73 74 20 70 6f 73 74 20 74  r a first post t
a350: 68 65 20 66 6f 72 75 6d 20 64 6f 65 73 20 6e 6f  he forum does no
a360: 74 20 68 61 76 65 2e 20 6f 63 78 32 20 74 68 72  t have. ocx2 thr
a370: 65 61 64 20 61 33 37 32 39 33 65 66 20 6f 6e 20  ead a37293ef on 
a380: 74 68 65 20 73 65 72 76 65 72 20 61 6e 73 77 65  the server answe
a390: 72 65 64 20 5c 22 61 33 37 32 39 33 65 66 20 6e  red \"a37293ef n
a3a0: 61 6d 65 73 20 6e 6f 20 74 69 63 6b 65 74 20 6f  ames no ticket o
a3b0: 72 20 66 6f 72 75 6d 20 74 68 72 65 61 64 5c 22  r forum thread\"
a3c0: 2e 20 57 69 74 68 20 74 46 2e 73 68 2c 20 69 76  . With tF.sh, iv
a3d0: 79 27 73 20 63 6c 6f 6e 65 20 70 75 6c 6c 65 64  y's clone pulled
a3e0: 20 74 68 65 20 68 61 6c 66 2d 77 72 69 74 74 65   the half-writte
a3f0: 6e 20 72 75 6e 20 36 38 36 37 38 38 63 32 e2 80  n run 686788c2â€
a400: a6 20 61 6e 64 20 69 6e 64 65 78 65 64 20 69 74  ¦ and indexed it
a410: 20 74 68 65 72 65 20 61 73 20 61 20 6e 65 77 20   there as a new 
a420: 74 68 72 65 61 64 20 28 66 6f 72 75 6d 70 6f 73  thread (forumpos
a430: 74 20 31 2c 20 65 76 65 6e 74 20 31 29 2c 20 77  t 1, event 1), w
a440: 68 69 6c 65 20 74 68 65 20 73 65 72 76 65 72 20  hile the server 
a450: 73 68 6f 77 73 20 30 20 61 6e 64 20 30 2e 22 2c  shows 0 and 0.",
a460: 0a 20 20 20 22 65 78 70 65 63 74 65 64 22 3a 20  .   "expected": 
a470: 22 64 6f 63 73 2f 70 72 6f 74 6f 63 6f 6c 2d 76  "docs/protocol-v
a480: 31 2d 74 6f 6f 6c 73 2e 6d 64 20 73 61 79 73 20  1-tools.md says 
a490: 72 65 73 75 6c 74 20 69 73 20 5c 22 66 6f 72 20  result is \"for 
a4a0: 63 72 65 61 74 65 2c 20 73 74 6f 70 2c 20 70 6f  create, stop, po
a4b0: 73 74 20 61 6e 64 20 61 75 64 69 74 2c 20 74 68  st and audit, th
a4c0: 65 20 68 61 73 68 20 6f 66 20 77 68 61 74 20 69  e hash of what i
a4d0: 74 20 77 72 6f 74 65 5c 22 2e 20 57 72 69 74 65  t wrote\". Write
a4e0: 54 68 72 65 61 64 27 73 20 41 42 4f 55 54 20 73  Thread's ABOUT s
a4f0: 61 79 73 20 69 74 20 77 72 69 74 65 73 20 5c 22  ays it writes \"
a500: 74 68 65 20 72 75 6e 20 61 73 20 74 68 65 20 66  the run as the f
a510: 69 72 73 74 20 70 6f 73 74 20 6f 66 20 61 20 6e  irst post of a n
a520: 65 77 20 74 68 72 65 61 64 5c 22 2c 20 61 6e 64  ew thread\", and
a530: 20 70 75 74 5f 70 6f 73 74 20 73 61 79 73 20 69   put_post says i
a540: 74 20 5c 22 69 6e 64 65 78 65 73 20 69 74 20 74  t \"indexes it t
a550: 68 65 72 65 5c 22 2e 20 53 6f 20 65 69 74 68 65  here\". So eithe
a560: 72 20 74 68 65 20 77 72 69 74 65 20 69 73 20 77  r the write is w
a570: 68 6f 6c 65 20 28 73 74 6f 72 65 64 20 61 6e 64  hole (stored and
a580: 20 69 6e 64 65 78 65 64 29 2c 20 6f 72 20 74 68   indexed), or th
a590: 65 20 61 6e 73 77 65 72 20 6e 61 6d 65 73 20 74  e answer names t
a5a0: 68 65 20 73 74 6f 72 65 64 20 68 61 73 68 20 61  he stored hash a
a5b0: 6e 64 20 73 61 79 73 20 69 74 20 69 73 20 6e 6f  nd says it is no
a5c0: 74 20 69 6e 64 65 78 65 64 2e 20 41 20 72 75 6e  t indexed. A run
a5d0: 20 72 65 70 6f 72 74 65 64 20 61 73 20 6e 6f 74   reported as not
a5e0: 20 77 72 69 74 74 65 6e 20 6d 75 73 74 20 6e 6f   written must no
a5f0: 74 20 62 65 20 6f 6e 65 20 74 68 65 20 6e 6f 64  t be one the nod
a600: 65 20 61 63 74 73 20 6f 6e 2e 20 54 68 65 20 69  e acts on. The i
a610: 64 65 6d 70 6f 74 65 6e 63 65 20 70 72 65 63 65  dempotence prece
a620: 70 74 20 73 61 79 73 20 61 20 62 65 68 61 76 69  pt says a behavi
a630: 6f 75 72 20 72 75 6e 20 74 77 69 63 65 20 66 6f  our run twice fo
a640: 72 20 74 68 65 20 73 61 6d 65 20 63 61 75 73 65  r the same cause
a650: 20 77 72 69 74 65 73 20 6f 6e 63 65 2c 20 61 6e   writes once, an
a660: 64 20 68 65 72 65 20 74 68 65 20 75 73 65 72 20  d here the user 
a670: 77 68 6f 20 77 61 73 20 74 6f 6c 64 20 69 74 20  who was told it 
a680: 66 61 69 6c 65 64 20 77 69 6c 6c 20 72 75 6e 20  failed will run 
a690: 63 72 65 61 74 65 20 61 67 61 69 6e 2e 22 2c 0a  create again.",.
a6a0: 20 20 20 22 63 6f 64 65 22 3a 20 22 73 72 63 2f     "code": "src/
a6b0: 6f 63 78 2f 66 6f 73 73 69 6c 2f 66 6f 72 75 6d  ocx/fossil/forum
a6c0: 2e 63 72 3a 39 35 2d 31 31 31 20 28 70 75 74 5f  .cr:95-111 (put_
a6d0: 70 6f 73 74 29 3a 20 74 68 65 20 61 72 74 69 66  post): the artif
a6e0: 61 63 74 20 67 6f 65 73 20 69 6e 20 77 69 74 68  act goes in with
a6f0: 20 6f 6e 65 20 66 6f 73 73 69 6c 20 63 6f 6d 6d   one fossil comm
a700: 61 6e 64 20 28 74 65 73 74 2d 63 6f 6e 74 65 6e  and (test-conten
a710: 74 2d 70 75 74 2c 20 6c 69 6e 65 20 31 30 32 29  t-put, line 102)
a720: 20 61 6e 64 20 69 73 20 69 6e 64 65 78 65 64 20   and is indexed 
a730: 77 69 74 68 20 61 6e 6f 74 68 65 72 20 28 74 65  with another (te
a740: 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 2c 20 6c 69  st-crosslink, li
a750: 6e 65 20 31 30 39 29 2e 20 45 61 63 68 20 72 75  ne 109). Each ru
a760: 6e 73 20 74 68 72 6f 75 67 68 20 69 74 73 20 6f  ns through its o
a770: 77 6e 20 50 6c 61 63 65 23 72 75 6e 2c 20 73 6f  wn Place#run, so
a780: 20 65 61 63 68 20 74 61 6b 65 73 20 61 6e 64 20   each takes and 
a790: 64 72 6f 70 73 20 46 6f 73 73 69 6c 2e 74 75 72  drops Fossil.tur
a7a0: 6e 20 28 73 72 63 2f 6f 63 78 2f 66 6f 73 73 69  n (src/ocx/fossi
a7b0: 6c 2e 63 72 3a 31 35 32 2d 31 35 39 2c 20 32 34  l.cr:152-159, 24
a7c0: 34 29 20 6f 6e 20 69 74 73 20 6f 77 6e 2e 20 4e  4) on its own. N
a7d0: 6f 74 68 69 6e 67 20 72 65 64 6f 65 73 20 74 68  othing redoes th
a7e0: 65 20 63 72 6f 73 73 6c 69 6e 6b 2c 20 61 6e 64  e crosslink, and
a7f0: 20 6e 6f 74 68 69 6e 67 20 72 65 6d 6f 76 65 73   nothing removes
a800: 20 74 68 65 20 61 72 74 69 66 61 63 74 20 77 68   the artifact wh
a810: 65 6e 20 74 68 65 20 63 72 6f 73 73 6c 69 6e 6b  en the crosslink
a820: 20 66 61 69 6c 73 2c 20 61 6e 64 20 74 68 65 20   fails, and the 
a830: 66 61 69 6c 75 72 65 20 6c 6f 73 65 73 20 74 68  failure loses th
a840: 65 20 68 61 73 68 2c 20 77 68 69 63 68 20 69 73  e hash, which is
a850: 20 6f 6e 6c 79 20 69 6e 20 74 68 65 20 6c 6f 63   only in the loc
a860: 61 6c 20 60 68 61 73 68 60 2e 20 73 72 63 2f 6f  al `hash`. src/o
a870: 63 78 2f 66 6f 73 73 69 6c 2e 63 72 3a 32 35 37  cx/fossil.cr:257
a880: 2d 32 35 38 20 62 75 69 6c 64 73 20 74 68 65 20  -258 builds the 
a890: 6d 65 73 73 61 67 65 2c 20 77 68 69 63 68 20 73  message, which s
a8a0: 61 79 73 20 5c 22 77 68 61 74 20 61 6e 20 65 61  ays \"what an ea
a8b0: 72 6c 69 65 72 20 63 6f 6d 6d 61 6e 64 20 77 72  rlier command wr
a8c0: 6f 74 65 20 73 74 61 79 73 5c 22 20 62 75 74 20  ote stays\" but 
a8d0: 6e 65 76 65 72 20 73 61 79 73 20 77 68 61 74 20  never says what 
a8e0: 74 68 61 74 20 77 61 73 2e 20 73 72 63 2f 6f 63  that was. src/oc
a8f0: 78 2f 66 6f 73 73 69 6c 2f 73 79 6e 63 2e 63 72  x/fossil/sync.cr
a900: 3a 32 33 37 2d 32 35 37 20 28 63 68 65 63 6b 65  :237-257 (checke
a910: 64 5f 6f 75 74 29 20 72 75 6e 73 20 74 68 65 20  d_out) runs the 
a920: 70 75 74 20 6f 6e 20 74 68 65 20 73 65 72 76 65  put on the serve
a930: 64 20 72 65 70 6f 73 69 74 6f 72 79 20 74 68 72  d repository thr
a940: 6f 75 67 68 20 61 20 74 65 6d 70 6f 72 61 72 79  ough a temporary
a950: 20 63 68 65 63 6b 6f 75 74 2c 20 61 6e 64 20 69   checkout, and i
a960: 74 73 20 63 6c 6f 73 65 20 74 68 65 6e 20 66 61  ts close then fa
a970: 69 6c 73 20 74 6f 6f 2e 20 43 61 6c 6c 65 72 73  ils too. Callers
a980: 3a 20 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e  : src/ocx/comman
a990: 64 73 2f 63 72 65 61 74 65 2e 63 72 3a 31 33 39  ds/create.cr:139
a9a0: 2f 31 36 33 2c 20 73 72 63 2f 6f 63 78 2f 63 6f  /163, src/ocx/co
a9b0: 6d 6d 61 6e 64 73 2f 73 74 6f 70 2e 63 72 3a 32  mmands/stop.cr:2
a9c0: 34 32 2c 20 73 72 63 2f 6f 63 78 2f 6e 6f 64 65  42, src/ocx/node
a9d0: 2e 63 72 3a 33 31 30 2f 33 34 30 2e 22 0a 20 20  .cr:310/340.".  
a9e0: 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65  },.  {.   "title
a9f0: 22 3a 20 22 41 20 63 6c 6f 6e 65 20 70 6f 73 74  ": "A clone post
aa00: 20 63 61 6e 20 62 65 20 6c 65 66 74 20 68 61 6c   can be left hal
aa10: 66 2d 77 72 69 74 74 65 6e 3a 20 74 68 65 20 66  f-written: the f
aa20: 61 69 6c 65 64 20 61 6e 73 77 65 72 20 6e 61 6d  ailed answer nam
aa30: 65 73 20 6e 6f 20 68 61 73 68 2c 20 74 68 65 20  es no hash, the 
aa40: 6e 65 78 74 20 70 75 73 68 20 73 65 6e 64 73 20  next push sends 
aa50: 74 68 65 20 70 6f 73 74 2c 20 73 6f 20 61 20 72  the post, so a r
aa60: 65 74 72 79 20 70 6f 73 74 73 20 74 77 69 63 65  etry posts twice
aa70: 2c 20 61 6e 64 20 74 68 65 20 63 6c 6f 6e 65 27  , and the clone'
aa80: 73 20 6f 77 6e 20 74 68 72 65 61 64 20 6e 65 76  s own thread nev
aa90: 65 72 20 73 68 6f 77 73 20 74 68 65 20 66 69 72  er shows the fir
aaa0: 73 74 20 63 6f 70 79 22 2c 0a 20 20 20 22 73 65  st copy",.   "se
aab0: 76 65 72 69 74 79 22 3a 20 22 68 69 67 68 22 2c  verity": "high",
aac0: 0a 20 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f  .   "reproductio
aad0: 6e 22 3a 20 22 53 61 6d 65 20 44 2c 20 65 6e 76  n": "Same D, env
aae0: 2c 20 73 68 69 6d 20 61 6e 64 20 68 6f 6c 64 65  , shim and holde
aaf0: 72 20 61 73 20 74 68 65 20 66 69 72 73 74 20 66  r as the first f
ab00: 69 6e 64 69 6e 67 2e 20 53 63 72 69 70 74 20 24  inding. Script $
ab10: 44 2f 74 41 2e 73 68 3a 20 24 44 2f 67 61 74 65  D/tA.sh: $D/gate
ab20: 2e 73 68 20 61 72 6d 20 74 65 73 74 2d 63 72 6f  .sh arm test-cro
ab30: 73 73 6c 69 6e 6b 2e 20 54 68 65 6e 20 63 64 20  sslink. Then cd 
ab40: 24 44 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74 72  $D/clones/ivy/tr
ab50: 65 65 20 61 6e 64 20 72 75 6e 20 69 6e 20 74 68  ee and run in th
ab60: 65 20 62 61 63 6b 67 72 6f 75 6e 64 3a 20 50 41  e background: PA
ab70: 54 48 3d 24 44 2f 73 68 69 6d 3a 24 50 41 54 48  TH=$D/shim:$PATH
ab80: 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d 6a 73 6f   nice ocx2 --jso
ab90: 6e 20 70 6f 73 74 20 64 36 37 37 35 37 30 36 20  n post d6775706 
aba0: 5c 22 72 65 70 6c 79 20 41 20 68 65 6c 64 20 62  \"reply A held b
abb0: 65 74 77 65 65 6e 20 70 75 74 20 61 6e 64 20 63  etween put and c
abc0: 72 6f 73 73 6c 69 6e 6b 5c 22 2e 20 54 68 65 6e  rosslink\". Then
abd0: 20 24 44 2f 67 61 74 65 2e 73 68 20 77 61 69 74   $D/gate.sh wait
abe0: 20 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 3b   test-crosslink;
abf0: 20 73 71 6c 69 74 65 33 20 24 44 2f 63 6c 6f 6e   sqlite3 $D/clon
ac00: 65 73 2f 69 76 79 2f 63 6c 6f 6e 65 2e 66 6f 73  es/ivy/clone.fos
ac10: 73 69 6c 20 74 61 6b 65 73 20 42 45 47 49 4e 20  sil takes BEGIN 
ac20: 49 4d 4d 45 44 49 41 54 45 3b 20 24 44 2f 67 61  IMMEDIATE; $D/ga
ac30: 74 65 2e 73 68 20 6f 70 65 6e 20 74 65 73 74 2d  te.sh open test-
ac40: 63 72 6f 73 73 6c 69 6e 6b 3b 20 77 61 69 74 20  crosslink; wait 
ac50: 66 6f 72 20 74 68 65 20 70 6f 73 74 3b 20 52 4f  for the post; RO
ac60: 4c 4c 42 41 43 4b 2e 20 54 68 65 6e 3a 20 73 71  LLBACK. Then: sq
ac70: 6c 69 74 65 33 20 24 44 2f 63 6c 6f 6e 65 73 2f  lite3 $D/clones/
ac80: 69 76 79 2f 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c  ivy/clone.fossil
ac90: 20 5c 22 73 65 6c 65 63 74 20 62 2e 72 69 64 2c   \"select b.rid,
aca0: 62 2e 75 75 69 64 2c 28 73 65 6c 65 63 74 20 63  b.uuid,(select c
acb0: 6f 75 6e 74 28 2a 29 20 66 72 6f 6d 20 66 6f 72  ount(*) from for
acc0: 75 6d 70 6f 73 74 20 66 20 77 68 65 72 65 20 66  umpost f where f
acd0: 2e 66 70 69 64 3d 62 2e 72 69 64 29 20 66 72 6f  .fpid=b.rid) fro
ace0: 6d 20 62 6c 6f 62 20 62 20 77 68 65 72 65 20 72  m blob b where r
acf0: 69 64 3e 3d 31 38 5c 22 2e 20 54 68 65 6e 20 61  id>=18\". Then a
ad00: 20 72 65 74 72 79 3a 20 6e 69 63 65 20 6f 63 78   retry: nice ocx
ad10: 32 20 2d 2d 6a 73 6f 6e 20 70 6f 73 74 20 64 36  2 --json post d6
ad20: 37 37 35 37 30 36 20 5c 22 72 65 70 6c 79 20 41  775706 \"reply A
ad30: 20 72 65 74 72 69 65 64 20 61 66 74 65 72 20 74   retried after t
ad40: 68 65 20 66 61 69 6c 75 72 65 5c 22 2e 20 54 68  he failure\". Th
ad50: 65 6e 20 63 6f 6d 70 61 72 65 20 6e 69 63 65 20  en compare nice 
ad60: 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 74 68 72 65  ocx2 --json thre
ad70: 61 64 20 64 36 37 37 35 37 30 36 20 28 72 75 6e  ad d6775706 (run
ad80: 20 69 6e 20 74 68 65 20 63 6c 6f 6e 65 29 20 77   in the clone) w
ad90: 69 74 68 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d  ith nice ocx2 --
ada0: 6a 73 6f 6e 20 2d 2d 72 65 70 6f 73 69 74 6f 72  json --repositor
adb0: 79 20 24 52 45 50 4f 20 2d 2d 75 73 65 72 20 6f  y $REPO --user o
adc0: 77 6e 65 72 20 74 68 72 65 61 64 20 64 36 37 37  wner thread d677
add0: 35 37 30 36 2e 22 2c 0a 20 20 20 22 6f 62 73 65  5706.",.   "obse
ade0: 72 76 65 64 22 3a 20 22 54 68 65 20 70 6f 73 74  rved": "The post
adf0: 20 61 6e 73 77 65 72 65 64 20 6f 6b 3a 66 61 6c   answered ok:fal
ae00: 73 65 20 77 69 74 68 20 6e 6f 20 72 65 73 75 6c  se with no resul
ae10: 74 2e 20 73 74 6f 70 70 65 64 20 77 61 73 3a 20  t. stopped was: 
ae20: 5c 22 66 6f 73 73 69 6c 20 74 65 73 74 2d 63 72  \"fossil test-cr
ae30: 6f 73 73 6c 69 6e 6b 20 6f 6e 20 e2 80 a6 2f 63  osslink on …/c
ae40: 6c 6f 6e 65 73 2f 69 76 79 2f 63 6c 6f 6e 65 2e  lones/ivy/clone.
ae50: 66 6f 73 73 69 6c 3a 20 61 20 77 72 69 74 65 72  fossil: a writer
ae60: 20 6f 75 74 73 69 64 65 20 4f 43 58 20 68 65 6c   outside OCX hel
ae70: 64 20 74 68 65 20 72 65 70 6f 73 69 74 6f 72 79  d the repository
ae80: 2c 20 73 6f 20 74 68 69 73 20 63 6f 6d 6d 61 6e  , so this comman
ae90: 64 20 66 61 69 6c 65 64 3b 20 77 68 61 74 20 61  d failed; what a
aea0: 6e 20 65 61 72 6c 69 65 72 20 63 6f 6d 6d 61 6e  n earlier comman
aeb0: 64 20 77 72 6f 74 65 20 73 74 61 79 73 3a 20 44  d wrote stays: D
aec0: 61 74 61 62 61 73 65 20 65 72 72 6f 72 3a 20 64  atabase error: d
aed0: 61 74 61 62 61 73 65 20 69 73 20 6c 6f 63 6b 65  atabase is locke
aee0: 64 3a 20 7b 52 45 50 4c 41 43 45 20 49 4e 54 4f  d: {REPLACE INTO
aef0: 20 66 6f 72 75 6d 70 6f 73 74 28 66 70 69 64 2c   forumpost(fpid,
af00: 66 72 6f 6f 74 2c 2e 2e 2e 29 56 41 4c 55 45 53  froot,...)VALUES
af10: 28 31 39 2c 31 34 2c 2e 2e 2e 29 7d 5c 22 2e 20  (19,14,...)}\". 
af20: 54 68 65 20 63 6c 6f 6e 65 20 68 65 6c 64 20 72  The clone held r
af30: 69 64 20 31 39 20 3d 20 62 33 65 64 37 39 62 35  id 19 = b3ed79b5
af40: 31 35 30 39 37 64 37 37 37 35 31 33 62 65 34 34  15097d777513be44
af50: 35 61 39 62 61 31 37 65 34 37 32 38 63 31 31 37  5a9ba17e4728c117
af60: 34 61 33 33 61 35 63 38 31 38 64 38 30 35 63 62  4a33a5c818d805cb
af70: 66 63 64 32 63 66 38 39 20 77 69 74 68 20 30 20  fcd2cf89 with 0 
af80: 66 6f 72 75 6d 70 6f 73 74 20 72 6f 77 73 2e 20  forumpost rows. 
af90: 54 68 65 20 72 65 74 72 79 20 61 6e 73 77 65 72  The retry answer
afa0: 65 64 20 6f 6b 3a 74 72 75 65 2c 20 77 72 69 74  ed ok:true, writ
afb0: 74 65 6e 20 37 63 33 39 30 37 64 35 e2 80 a6 2c  ten 7c3907d5…,
afc0: 20 61 6e 64 20 69 74 73 20 70 75 73 68 20 61 6c   and its push al
afd0: 73 6f 20 63 61 72 72 69 65 64 20 62 33 65 64 37  so carried b3ed7
afe0: 39 62 35 2e 20 54 68 65 20 73 65 72 76 65 72 20  9b5. The server 
aff0: 74 68 65 6e 20 6c 69 73 74 65 64 20 62 6f 74 68  then listed both
b000: 20 61 73 20 69 76 79 27 73 20 70 6f 73 74 73 3a   as ivy's posts:
b010: 20 27 37 63 33 39 30 37 64 35 20 69 76 79 20 72   '7c3907d5 ivy r
b020: 65 70 6c 79 20 41 20 72 65 74 72 69 65 64 20 61  eply A retried a
b030: 66 74 65 72 20 74 68 65 20 66 61 69 6c 75 72 65  fter the failure
b040: 27 20 61 6e 64 20 27 62 33 65 64 37 39 62 35 20  ' and 'b3ed79b5 
b050: 69 76 79 20 72 65 70 6c 79 20 41 20 68 65 6c 64  ivy reply A held
b060: 20 62 65 74 77 65 65 6e 20 70 75 74 20 61 6e 64   between put and
b070: 20 63 72 6f 73 73 6c 69 6e 6b 27 2e 20 6f 63 78   crosslink'. ocx
b080: 32 20 74 68 72 65 61 64 20 72 75 6e 20 69 6e 20  2 thread run in 
b090: 69 76 79 27 73 20 63 6c 6f 6e 65 20 6c 69 73 74  ivy's clone list
b0a0: 73 20 37 63 33 39 30 37 64 35 20 62 75 74 20 6e  s 7c3907d5 but n
b0b0: 65 76 65 72 20 62 33 65 64 37 39 62 35 2c 20 65  ever b3ed79b5, e
b0c0: 76 65 6e 20 61 66 74 65 72 20 70 75 6c 6c 69 6e  ven after pullin
b0d0: 67 3a 20 74 68 65 20 63 6c 6f 6e 65 20 61 6c 72  g: the clone alr
b0e0: 65 61 64 79 20 68 61 73 20 74 68 65 20 62 6c 6f  eady has the blo
b0f0: 62 2c 20 73 6f 20 61 20 70 75 6c 6c 20 6e 65 76  b, so a pull nev
b100: 65 72 20 69 6e 64 65 78 65 73 20 69 74 2e 22 2c  er indexes it.",
b110: 0a 20 20 20 22 65 78 70 65 63 74 65 64 22 3a 20  .   "expected": 
b120: 22 50 75 74 50 6f 73 74 27 73 20 41 42 4f 55 54  "PutPost's ABOUT
b130: 20 73 61 79 73 20 69 74 20 77 69 6c 6c 20 5c 22   says it will \"
b140: 70 75 74 20 74 68 65 20 72 65 70 6c 79 20 69 6e  put the reply in
b150: 74 6f 20 74 68 65 20 63 61 6c 6c 65 72 27 73 20  to the caller's 
b160: 63 6c 6f 6e 65 20 61 73 20 46 6f 73 73 69 6c 27  clone as Fossil'
b170: 73 20 66 6f 72 75 6d 20 61 72 74 69 66 61 63 74  s forum artifact
b180: 2c 20 69 6e 64 65 78 20 69 74 20 74 68 65 72 65  , index it there
b190: 2c 20 61 6e 64 20 70 75 73 68 20 69 74 5c 22 2e  , and push it\".
b1a0: 20 54 68 65 20 70 6f 73 74 20 74 6f 6f 6c 27 73   The post tool's
b1b0: 20 6f 75 74 70 75 74 20 66 69 65 6c 64 20 60 77   output field `w
b1c0: 72 69 74 74 65 6e 60 20 69 73 20 5c 22 74 68 65  ritten` is \"the
b1d0: 20 70 6f 73 74 20 6f 72 20 74 69 63 6b 65 74 20   post or ticket 
b1e0: 63 68 61 6e 67 65 20 77 72 69 74 74 65 6e 2c 20  change written, 
b1f0: 62 79 20 69 74 73 20 68 61 73 68 5c 22 2e 20 41  by its hash\". A
b200: 20 70 6f 73 74 20 74 68 61 74 20 64 69 64 20 72   post that did r
b210: 65 61 63 68 20 74 68 65 20 73 65 72 76 65 72 20  each the server 
b220: 6d 75 73 74 20 6e 6f 74 20 62 65 20 72 65 70 6f  must not be repo
b230: 72 74 65 64 20 61 73 20 75 6e 77 72 69 74 74 65  rted as unwritte
b240: 6e 20 77 69 74 68 6f 75 74 20 69 74 73 20 68 61  n without its ha
b250: 73 68 2e 20 54 68 65 20 63 6c 6f 6e 65 27 73 20  sh. The clone's 
b260: 6f 77 6e 20 72 65 61 64 69 6e 67 20 6f 66 20 74  own reading of t
b270: 68 65 20 74 68 72 65 61 64 20 6d 75 73 74 20 6d  he thread must m
b280: 61 74 63 68 20 74 68 65 20 73 65 72 76 65 72 27  atch the server'
b290: 73 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22 3a 20  s.",.   "code": 
b2a0: 22 73 72 63 2f 6f 63 78 2f 66 6f 73 73 69 6c 2f  "src/ocx/fossil/
b2b0: 66 6f 72 75 6d 2e 63 72 3a 39 39 2d 31 31 30 3a  forum.cr:99-110:
b2c0: 20 74 65 73 74 2d 63 6f 6e 74 65 6e 74 2d 70 75   test-content-pu
b2d0: 74 20 61 6e 64 20 74 65 73 74 2d 63 72 6f 73 73  t and test-cross
b2e0: 6c 69 6e 6b 20 61 72 65 20 73 65 70 61 72 61 74  link are separat
b2f0: 65 20 74 75 72 6e 73 20 77 69 74 68 20 6e 6f 20  e turns with no 
b300: 72 65 63 6f 76 65 72 79 2e 20 73 72 63 2f 6f 63  recovery. src/oc
b310: 78 2f 63 6f 6d 6d 61 6e 64 73 2f 70 6f 73 74 2e  x/commands/post.
b320: 63 72 3a 32 37 2d 33 33 20 28 50 75 74 50 6f 73  cr:27-33 (PutPos
b330: 74 23 70 65 72 66 6f 72 6d 29 3a 20 61 20 72 61  t#perform): a ra
b340: 69 73 65 64 20 46 6f 73 73 69 6c 3a 3a 46 61 69  ised Fossil::Fai
b350: 6c 65 64 20 6c 6f 73 65 73 20 60 68 61 73 68 60  led loses `hash`
b360: 2e 20 73 72 63 2f 6f 63 78 2f 66 6f 73 73 69 6c  . src/ocx/fossil
b370: 2e 63 72 3a 32 35 37 2d 32 35 38 20 69 73 20 74  .cr:257-258 is t
b380: 68 65 20 67 65 6e 65 72 69 63 20 6d 65 73 73 61  he generic messa
b390: 67 65 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20  ge.".  },.  {.  
b3a0: 20 22 74 69 74 6c 65 22 3a 20 22 41 20 70 6f 73   "title": "A pos
b3b0: 74 20 6f 72 20 74 69 63 6b 65 74 20 63 6f 6d 6d  t or ticket comm
b3c0: 65 6e 74 20 77 72 69 74 74 65 6e 20 69 6e 20 74  ent written in t
b3d0: 68 65 20 63 6c 6f 6e 65 20 77 68 6f 73 65 20 70  he clone whose p
b3e0: 75 73 68 20 6d 65 65 74 73 20 61 6e 20 6f 75 74  ush meets an out
b3f0: 73 69 64 65 20 6c 6f 63 6b 20 69 73 20 72 65 70  side lock is rep
b400: 6f 72 74 65 64 20 61 73 20 66 61 69 6c 65 64 20  orted as failed 
b410: 77 69 74 68 20 6e 6f 20 68 61 73 68 2c 20 79 65  with no hash, ye
b420: 74 20 74 68 65 20 6e 65 78 74 20 73 79 6e 63 20  t the next sync 
b430: 73 65 6e 64 73 20 69 74 22 2c 0a 20 20 20 22 73  sends it",.   "s
b440: 65 76 65 72 69 74 79 22 3a 20 22 6d 65 64 69 75  everity": "mediu
b450: 6d 22 2c 0a 20 20 20 22 72 65 70 72 6f 64 75 63  m",.   "reproduc
b460: 74 69 6f 6e 22 3a 20 22 53 61 6d 65 20 73 65 74  tion": "Same set
b470: 75 70 2e 20 53 63 72 69 70 74 20 24 44 2f 74 45  up. Script $D/tE
b480: 2e 73 68 3a 20 24 44 2f 67 61 74 65 2e 73 68 20  .sh: $D/gate.sh 
b490: 61 72 6d 20 70 75 73 68 2e 20 54 68 65 6e 20 63  arm push. Then c
b4a0: 64 20 24 44 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f  d $D/clones/ivy/
b4b0: 74 72 65 65 20 61 6e 64 20 72 75 6e 20 69 6e 20  tree and run in 
b4c0: 74 68 65 20 62 61 63 6b 67 72 6f 75 6e 64 3a 20  the background: 
b4d0: 50 41 54 48 3d 24 44 2f 73 68 69 6d 3a 24 50 41  PATH=$D/shim:$PA
b4e0: 54 48 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d 6a  TH nice ocx2 --j
b4f0: 73 6f 6e 20 70 6f 73 74 20 64 36 37 37 35 37 30  son post d677570
b500: 36 20 5c 22 72 65 70 6c 79 20 45 20 68 65 6c 64  6 \"reply E held
b510: 20 62 65 66 6f 72 65 20 70 75 73 68 5c 22 2e 20   before push\". 
b520: 54 68 65 6e 20 24 44 2f 67 61 74 65 2e 73 68 20  Then $D/gate.sh 
b530: 77 61 69 74 20 70 75 73 68 3b 20 73 71 6c 69 74  wait push; sqlit
b540: 65 33 20 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 20  e3 clone.fossil 
b550: 74 61 6b 65 73 20 42 45 47 49 4e 20 49 4d 4d 45  takes BEGIN IMME
b560: 44 49 41 54 45 3b 20 24 44 2f 67 61 74 65 2e 73  DIATE; $D/gate.s
b570: 68 20 6f 70 65 6e 20 70 75 73 68 3b 20 77 61 69  h open push; wai
b580: 74 3b 20 52 4f 4c 4c 42 41 43 4b 2e 20 24 44 2f  t; ROLLBACK. $D/
b590: 74 4c 2e 73 68 20 69 73 20 74 68 65 20 73 61 6d  tL.sh is the sam
b5a0: 65 20 66 6f 72 20 61 20 74 69 63 6b 65 74 3a 20  e for a ticket: 
b5b0: 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 70 6f 73 74  ocx2 --json post
b5c0: 20 38 31 34 61 36 33 66 38 20 5c 22 74 69 63 6b   814a63f8 \"tick
b5d0: 65 74 20 63 6f 6d 6d 65 6e 74 20 4c 20 68 65 6c  et comment L hel
b5e0: 64 20 62 65 66 6f 72 65 20 70 75 73 68 5c 22 2e  d before push\".
b5f0: 20 41 66 74 65 72 20 62 6f 74 68 2c 20 61 6e 79   After both, any
b600: 20 6c 61 74 65 72 20 6f 63 78 32 20 70 6f 73 74   later ocx2 post
b610: 20 66 72 6f 6d 20 74 68 65 20 63 6c 6f 6e 65 2e   from the clone.
b620: 20 54 68 65 6e 20 73 71 6c 69 74 65 33 20 24 52   Then sqlite3 $R
b630: 45 50 4f 20 5c 22 73 65 6c 65 63 74 20 73 75 62  EPO \"select sub
b640: 73 74 72 28 75 75 69 64 2c 31 2c 38 29 2c 28 73  str(uuid,1,8),(s
b650: 65 6c 65 63 74 20 75 2e 6c 6f 67 69 6e 20 66 72  elect u.login fr
b660: 6f 6d 20 72 63 76 66 72 6f 6d 20 72 20 6a 6f 69  om rcvfrom r joi
b670: 6e 20 75 73 65 72 20 75 20 6f 6e 20 75 2e 75 69  n user u on u.ui
b680: 64 3d 72 2e 75 69 64 20 77 68 65 72 65 20 72 2e  d=r.uid where r.
b690: 72 63 76 69 64 3d 62 2e 72 63 76 69 64 29 20 66  rcvid=b.rcvid) f
b6a0: 72 6f 6d 20 62 6c 6f 62 20 62 20 77 68 65 72 65  rom blob b where
b6b0: 20 75 75 69 64 20 6c 69 6b 65 20 27 63 63 36 65   uuid like 'cc6e
b6c0: 33 63 39 65 25 27 20 6f 72 20 75 75 69 64 20 6c  3c9e%' or uuid l
b6d0: 69 6b 65 20 27 32 32 61 66 36 65 61 63 25 27 5c  ike '22af6eac%'\
b6e0: 22 2e 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65  ".",.   "observe
b6f0: 64 22 3a 20 22 42 6f 74 68 20 61 6e 73 77 65 72  d": "Both answer
b700: 65 64 20 6f 6b 3a 66 61 6c 73 65 20 77 69 74 68  ed ok:false with
b710: 20 6e 6f 20 72 65 73 75 6c 74 2e 20 73 74 6f 70   no result. stop
b720: 70 65 64 20 77 61 73 3a 20 5c 22 66 6f 73 73 69  ped was: \"fossi
b730: 6c 20 70 75 73 68 20 6f 6e 20 e2 80 a6 2f 63 6c  l push on …/cl
b740: 6f 6e 65 2e 66 6f 73 73 69 6c 3a 20 61 20 77 72  one.fossil: a wr
b750: 69 74 65 72 20 6f 75 74 73 69 64 65 20 4f 43 58  iter outside OCX
b760: 20 68 65 6c 64 20 74 68 65 20 72 65 70 6f 73 69   held the reposi
b770: 74 6f 72 79 2c 20 73 6f 20 74 68 69 73 20 63 6f  tory, so this co
b780: 6d 6d 61 6e 64 20 66 61 69 6c 65 64 3b 20 77 68  mmand failed; wh
b790: 61 74 20 61 6e 20 65 61 72 6c 69 65 72 20 63 6f  at an earlier co
b7a0: 6d 6d 61 6e 64 20 77 72 6f 74 65 20 73 74 61 79  mmand wrote stay
b7b0: 73 3a 20 50 75 73 68 20 74 6f 20 68 74 74 70 3a  s: Push to http:
b7c0: 2f 2f 69 76 79 40 31 32 37 2e 30 2e 30 2e 31 3a  //ivy@127.0.0.1:
b7d0: 31 38 39 33 34 2f 20 44 61 74 61 62 61 73 65 20  18934/ Database 
b7e0: 65 72 72 6f 72 3a 20 64 61 74 61 62 61 73 65 20  error: database 
b7f0: 69 73 20 6c 6f 63 6b 65 64 3a 20 7b 44 45 4c 45  is locked: {DELE
b800: 54 45 20 46 52 4f 4d 20 75 6e 73 65 6e 74 7d 5c  TE FROM unsent}\
b810: 22 2e 20 54 68 65 20 63 6c 6f 6e 65 20 6b 65 70  ". The clone kep
b820: 74 20 70 6f 73 74 20 63 63 36 65 33 63 39 65 e2  t post cc6e3c9eâ
b830: 80 a6 20 28 69 6e 64 65 78 65 64 29 20 61 6e 64  €¦ (indexed) and
b840: 20 74 69 63 6b 65 74 20 63 68 61 6e 67 65 20 32   ticket change 2
b850: 32 61 66 36 65 61 63 e2 80 a6 20 28 75 6e 73 65  2af6eac… (unse
b860: 6e 74 20 31 29 2e 20 54 68 65 20 6e 65 78 74 20  nt 1). The next 
b870: 4f 43 58 20 70 6f 73 74 20 70 75 73 68 65 64 20  OCX post pushed 
b880: 62 6f 74 68 2c 20 61 6e 64 20 74 68 65 20 73 65  both, and the se
b890: 72 76 65 72 20 74 68 65 6e 20 68 65 6c 64 20 63  rver then held c
b8a0: 63 36 65 33 63 39 65 20 28 72 69 64 20 32 35 29  c6e3c9e (rid 25)
b8b0: 20 61 6e 64 20 32 32 61 66 36 65 61 63 20 28 72   and 22af6eac (r
b8c0: 69 64 20 35 39 29 2c 20 65 61 63 68 20 72 65 63  id 59), each rec
b8d0: 65 69 76 65 64 20 66 72 6f 6d 20 69 76 79 2e 22  eived from ivy."
b8e0: 2c 0a 20 20 20 22 65 78 70 65 63 74 65 64 22 3a  ,.   "expected":
b8f0: 20 22 57 72 69 74 65 73 2e 63 6f 6d 6d 65 6e 74   "Writes.comment
b900: 20 61 6e 64 20 50 75 74 50 6f 73 74 20 61 6c 72   and PutPost alr
b910: 65 61 64 79 20 68 61 76 65 20 61 6e 20 61 6e 73  eady have an ans
b920: 77 65 72 20 66 6f 72 20 74 68 65 20 63 61 73 65  wer for the case
b930: 20 77 68 65 72 65 20 74 68 65 20 70 75 73 68 20   where the push 
b940: 64 6f 65 73 20 6e 6f 74 20 72 65 61 63 68 20 74  does not reach t
b950: 68 65 20 73 65 72 76 65 72 3a 20 5c 22 74 68 65  he server: \"the
b960: 20 63 68 61 6e 67 65 20 69 73 20 69 6e 20 74 68   change is in th
b970: 65 20 63 6c 6f 6e 65 2c 20 62 75 74 20 69 74 73  e clone, but its
b980: 20 70 75 73 68 20 64 69 64 20 6e 6f 74 20 72 65   push did not re
b990: 61 63 68 20 74 68 65 20 73 65 72 76 65 64 20 72  ach the served r
b9a0: 65 70 6f 73 69 74 6f 72 79 20 28 2e 2e 2e 29 3b  epository (...);
b9b0: 20 61 20 6c 61 74 65 72 20 73 79 6e 63 20 73 65   a later sync se
b9c0: 6e 64 73 20 69 74 5c 22 20 28 73 72 63 2f 6f 63  nds it\" (src/oc
b9d0: 78 2f 77 72 69 74 65 73 2e 63 72 3a 33 34 2c 20  x/writes.cr:34, 
b9e0: 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73  src/ocx/commands
b9f0: 2f 70 6f 73 74 2e 63 72 3a 33 31 29 2e 20 41 20  /post.cr:31). A 
ba00: 70 75 73 68 20 73 74 6f 70 70 65 64 20 62 79 20  push stopped by 
ba10: 61 20 6c 6f 63 6b 20 69 73 20 74 68 65 20 73 61  a lock is the sa
ba20: 6d 65 20 73 74 61 74 65 2c 20 73 6f 20 69 74 20  me state, so it 
ba30: 73 68 6f 75 6c 64 20 67 65 74 20 74 68 61 74 20  should get that 
ba40: 61 6e 73 77 65 72 2c 20 61 6e 64 20 62 6f 74 68  answer, and both
ba50: 20 61 6e 73 77 65 72 73 20 73 68 6f 75 6c 64 20   answers should 
ba60: 6e 61 6d 65 20 74 68 65 20 68 61 73 68 2c 20 77  name the hash, w
ba70: 68 69 63 68 20 74 68 65 20 70 72 6f 74 6f 63 6f  hich the protoco
ba80: 6c 20 70 75 74 73 20 69 6e 20 60 72 65 73 75 6c  l puts in `resul
ba90: 74 60 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22 3a  t`.",.   "code":
baa0: 20 22 73 72 63 2f 6f 63 78 2f 77 72 69 74 65 73   "src/ocx/writes
bab0: 2e 63 72 3a 33 31 2d 33 35 20 61 6e 64 20 73 72  .cr:31-35 and sr
bac0: 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f 70  c/ocx/commands/p
bad0: 6f 73 74 2e 63 72 3a 32 38 2d 33 32 20 68 61 6e  ost.cr:28-32 han
bae0: 64 6c 65 20 6f 6e 6c 79 20 74 68 65 20 63 61 73  dle only the cas
baf0: 65 20 77 68 65 72 65 20 50 75 73 68 65 64 23 75  e where Pushed#u
bb00: 6e 73 79 6e 63 65 64 20 69 73 20 73 65 74 2e 20  nsynced is set. 
bb10: 46 6f 73 73 69 6c 3a 3a 50 6c 61 63 65 23 70 75  Fossil::Place#pu
bb20: 73 68 20 28 73 72 63 2f 6f 63 78 2f 66 6f 73 73  sh (src/ocx/foss
bb30: 69 6c 2f 73 79 6e 63 2e 63 72 3a 33 35 38 2d 33  il/sync.cr:358-3
bb40: 36 31 29 20 72 61 69 73 65 73 20 6f 75 74 20 6f  61) raises out o
bb50: 66 20 50 6c 61 63 65 23 72 75 6e 27 73 20 6c 6f  f Place#run's lo
bb60: 63 6b 65 64 20 62 72 61 6e 63 68 20 28 73 72 63  cked branch (src
bb70: 2f 6f 63 78 2f 66 6f 73 73 69 6c 2e 63 72 3a 32  /ocx/fossil.cr:2
bb80: 35 38 29 20 62 65 66 6f 72 65 20 74 68 61 74 20  58) before that 
bb90: 63 68 65 63 6b 20 72 75 6e 73 2c 20 61 6e 64 20  check runs, and 
bba0: 74 68 65 20 63 68 61 6e 67 65 27 73 20 68 61 73  the change's has
bbb0: 68 20 69 73 20 64 72 6f 70 70 65 64 2e 22 0a 20  h is dropped.". 
bbc0: 20 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c   },.  {.   "titl
bbd0: 65 22 3a 20 22 41 20 6e 6f 64 65 27 73 20 72 65  e": "A node's re
bbe0: 70 6f 72 74 20 6c 65 66 74 20 68 61 6c 66 2d 77  port left half-w
bbf0: 72 69 74 74 65 6e 20 62 79 20 61 6e 20 6f 75 74  ritten by an out
bc00: 73 69 64 65 20 77 72 69 74 65 72 20 6d 61 6b 65  side writer make
bc10: 73 20 70 6f 6c 6c 20 2d 2d 63 68 65 63 6b 20 77  s poll --check w
bc20: 72 69 74 65 20 61 20 73 65 63 6f 6e 64 20 60 65  rite a second `e
bc30: 6e 64 65 64 60 20 66 6f 72 20 74 68 65 20 73 61  nded` for the sa
bc40: 6d 65 20 72 75 6e 3b 20 74 68 65 20 66 61 69 6c  me run; the fail
bc50: 65 64 20 70 6f 6c 6c 20 77 72 69 74 65 73 20 6e  ed poll writes n
bc60: 6f 20 68 6f 6f 6b 2d 6c 6f 67 20 6c 69 6e 65 22  o hook-log line"
bc70: 2c 0a 20 20 20 22 73 65 76 65 72 69 74 79 22 3a  ,.   "severity":
bc80: 20 22 6d 65 64 69 75 6d 22 2c 0a 20 20 20 22 72   "medium",.   "r
bc90: 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a 20 22 53  eproduction": "S
bca0: 61 6d 65 20 73 65 74 75 70 2c 20 77 69 74 68 20  ame setup, with 
bcb0: 6e 6f 64 65 20 6e 6f 64 65 61 20 72 65 67 69 73  node nodea regis
bcc0: 74 65 72 65 64 20 61 6e 64 20 61 70 70 72 6f 76  tered and approv
bcd0: 65 64 20 61 73 20 69 6e 20 74 68 65 20 66 69 72  ed as in the fir
bce0: 73 74 20 66 69 6e 64 69 6e 67 2e 20 53 63 72 69  st finding. Scri
bcf0: 70 74 20 24 44 2f 74 50 2e 73 68 3a 20 28 31 29  pt $D/tP.sh: (1)
bd00: 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d 6a 73 6f   nice ocx2 --jso
bd10: 6e 20 2d 2d 72 65 70 6f 73 69 74 6f 72 79 20 24  n --repository $
bd20: 52 45 50 4f 20 2d 2d 75 73 65 72 20 6f 77 6e 65  REPO --user owne
bd30: 72 20 63 72 65 61 74 65 20 5c 22 52 75 6e 20 50  r create \"Run P
bd40: 20 66 6f 72 20 6e 6f 64 65 61 5c 22 20 2d 2d 6e   for nodea\" --n
bd50: 6f 64 65 20 6e 6f 64 65 61 20 2d 2d 66 69 65 6c  ode nodea --fiel
bd60: 64 73 20 27 7b 5c 22 70 72 6f 63 65 73 73 5c 22  ds '{\"process\"
bd70: 3a 7b 5c 22 75 73 65 72 5c 22 3a 5c 22 6f 74 74  :{\"user\":\"ott
bd80: 6f 5c 22 2c 5c 22 63 6f 6d 6d 61 6e 64 5c 22 3a  o\",\"command\":
bd90: 5b 5c 22 74 72 75 65 5c 22 5d 7d 7d 27 20 77 72  [\"true\"]}}' wr
bda0: 6f 74 65 20 38 35 36 62 31 34 36 65 e2 80 a6 2e  ote 856b146e….
bdb0: 20 28 32 29 20 24 44 2f 67 61 74 65 2e 73 68 20   (2) $D/gate.sh 
bdc0: 61 72 6d 20 74 65 73 74 2d 63 72 6f 73 73 6c 69  arm test-crossli
bdd0: 6e 6b 2e 20 28 33 29 20 49 6e 20 74 68 65 20 62  nk. (3) In the b
bde0: 61 63 6b 67 72 6f 75 6e 64 3a 20 50 41 54 48 3d  ackground: PATH=
bdf0: 24 44 2f 73 68 69 6d 3a 24 50 41 54 48 20 6e 69  $D/shim:$PATH ni
be00: 63 65 20 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 2d  ce ocx2 --json -
be10: 2d 72 65 70 6f 73 69 74 6f 72 79 20 24 44 2f 6e  -repository $D/n
be20: 6f 64 65 2f 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c  ode/clone.fossil
be30: 20 70 6f 6c 6c 20 24 55 52 4c 20 24 44 2f 6e 6f   poll $URL $D/no
be40: 64 65 2f 6e 6f 64 65 2e 6a 73 6f 6e 2e 20 28 34  de/node.json. (4
be50: 29 20 24 44 2f 67 61 74 65 2e 73 68 20 77 61 69  ) $D/gate.sh wai
be60: 74 20 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b  t test-crosslink
be70: 3b 20 73 71 6c 69 74 65 33 20 24 44 2f 6e 6f 64  ; sqlite3 $D/nod
be80: 65 2f 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 20 74  e/clone.fossil t
be90: 61 6b 65 73 20 42 45 47 49 4e 20 49 4d 4d 45 44  akes BEGIN IMMED
bea0: 49 41 54 45 3b 20 24 44 2f 67 61 74 65 2e 73 68  IATE; $D/gate.sh
beb0: 20 6f 70 65 6e 20 74 65 73 74 2d 63 72 6f 73 73   open test-cross
bec0: 6c 69 6e 6b 3b 20 77 61 69 74 3b 20 52 4f 4c 4c  link; wait; ROLL
bed0: 42 41 43 4b 2e 20 28 35 29 20 50 6f 6c 6c 20 61  BACK. (5) Poll a
bee0: 67 61 69 6e 20 77 69 74 68 6f 75 74 20 2d 2d 63  gain without --c
bef0: 68 65 63 6b 2e 20 28 36 29 20 50 6f 6c 6c 20 77  heck. (6) Poll w
bf00: 69 74 68 20 2d 2d 63 68 65 63 6b 2e 20 28 37 29  ith --check. (7)
bf10: 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d 6a 73 6f   nice ocx2 --jso
bf20: 6e 20 2d 2d 72 65 70 6f 73 69 74 6f 72 79 20 24  n --repository $
bf30: 52 45 50 4f 20 2d 2d 75 73 65 72 20 6f 77 6e 65  REPO --user owne
bf40: 72 20 74 68 72 65 61 64 20 38 35 36 62 31 34 36  r thread 856b146
bf50: 65 2e 20 28 38 29 20 74 61 69 6c 20 24 44 2f 72  e. (8) tail $D/r
bf60: 6f 6f 74 2f 6e 6f 64 65 2f 68 6f 6f 6b 2e 6c 6f  oot/node/hook.lo
bf70: 67 2e 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65  g.",.   "observe
bf80: 64 22 3a 20 22 54 68 65 20 66 69 72 73 74 20 70  d": "The first p
bf90: 6f 6c 6c 20 61 6e 73 77 65 72 65 64 20 6f 6b 3a  oll answered ok:
bfa0: 66 61 6c 73 65 20 28 74 65 73 74 2d 63 72 6f 73  false (test-cros
bfb0: 73 6c 69 6e 6b 20 6f 6e 20 6e 6f 64 65 2f 63 6c  slink on node/cl
bfc0: 6f 6e 65 2e 66 6f 73 73 69 6c 3a 20 64 61 74 61  one.fossil: data
bfd0: 62 61 73 65 20 69 73 20 6c 6f 63 6b 65 64 20 e2  base is locked â
bfe0: 80 a6 29 2e 20 49 74 73 20 72 65 70 6f 72 74 20  €¦). Its report 
bff0: 38 32 65 36 37 37 63 38 e2 80 a6 20 73 74 61 79  82e677c8… stay
c000: 65 64 20 69 6e 20 74 68 65 20 6e 6f 64 65 20 63  ed in the node c
c010: 6c 6f 6e 65 20 77 69 74 68 20 30 20 66 6f 72 75  lone with 0 foru
c020: 6d 70 6f 73 74 20 72 6f 77 73 2c 20 61 6e 64 20  mpost rows, and 
c030: 6e 6f 20 6c 69 6e 65 20 77 61 73 20 61 64 64 65  no line was adde
c040: 64 20 74 6f 20 72 6f 6f 74 2f 6e 6f 64 65 2f 68  d to root/node/h
c050: 6f 6f 6b 2e 6c 6f 67 2e 20 54 68 65 20 6e 65 78  ook.log. The nex
c060: 74 20 6f 72 64 69 6e 61 72 79 20 70 6f 6c 6c 20  t ordinary poll 
c070: 61 6e 73 77 65 72 65 64 20 61 72 74 69 66 61 63  answered artifac
c080: 74 73 20 5b 5d 2c 20 61 6e 73 77 65 72 65 64 20  ts [], answered 
c090: 5b 5d 3a 20 74 68 65 20 70 75 6c 6c 65 64 20 72  []: the pulled r
c0a0: 75 6e 20 77 61 73 20 6e 6f 74 20 6c 6f 6f 6b 65  un was not looke
c0b0: 64 20 61 74 20 61 67 61 69 6e 2e 20 54 68 65 20  d at again. The 
c0c0: 2d 2d 63 68 65 63 6b 20 70 6f 6c 6c 20 73 61 77  --check poll saw
c0d0: 20 6e 6f 20 60 65 6e 64 65 64 60 20 28 74 68 65   no `ended` (the
c0e0: 20 66 69 72 73 74 20 6f 6e 65 20 69 73 20 6e 6f   first one is no
c0f0: 74 20 69 6e 64 65 78 65 64 29 20 61 6e 64 20 77  t indexed) and w
c100: 72 6f 74 65 20 61 20 73 65 63 6f 6e 64 20 72 65  rote a second re
c110: 66 75 73 61 6c 2c 20 30 38 35 66 35 34 32 66 e2  fusal, 085f542fâ
c120: 80 a6 2e 20 49 74 73 20 70 75 73 68 20 73 65 6e  €¦. Its push sen
c130: 74 20 62 6f 74 68 2e 20 54 68 65 20 73 65 72 76  t both. The serv
c140: 65 72 20 74 68 72 65 61 64 20 66 6f 72 20 38 35  er thread for 85
c150: 36 62 31 34 36 65 20 6e 6f 77 20 68 6f 6c 64 73  6b146e now holds
c160: 20 6f 77 6e 65 72 27 73 20 72 75 6e 20 70 6c 75   owner's run plu
c170: 73 20 74 77 6f 20 70 6f 73 74 73 20 62 79 20 6e  s two posts by n
c180: 6f 64 65 61 20 77 69 74 68 20 5c 22 6b 69 6e 64  odea with \"kind
c190: 5c 22 3a 20 5c 22 65 6e 64 65 64 5c 22 20 28 30  \": \"ended\" (0
c1a0: 38 35 66 35 34 32 66 20 61 6e 64 20 38 32 65 36  85f542f and 82e6
c1b0: 37 37 63 38 29 2e 22 2c 0a 20 20 20 22 65 78 70  77c8).",.   "exp
c1c0: 65 63 74 65 64 22 3a 20 22 50 72 65 63 65 70 74  ected": "Precept
c1d0: 20 69 64 65 6d 70 6f 74 65 6e 63 65 3a 20 5c 22   idempotence: \"
c1e0: 61 20 62 65 68 61 76 69 6f 72 20 72 75 6e 20 74  a behavior run t
c1f0: 77 69 63 65 20 66 6f 72 20 74 68 65 20 73 61 6d  wice for the sam
c200: 65 20 63 61 75 73 69 6e 67 20 61 72 74 69 66 61  e causing artifa
c210: 63 74 20 77 72 69 74 65 73 20 6f 6e 63 65 5c 22  ct writes once\"
c220: 2e 20 64 6f 63 73 2f 70 72 6f 74 6f 63 6f 6c 2d  . docs/protocol-
c230: 76 31 2d 66 6f 73 73 69 6c 2e 6d 64 20 28 6e 6f  v1-fossil.md (no
c240: 64 65 20 63 68 65 63 6b 29 20 68 61 73 20 74 68  de check) has th
c250: 65 20 61 64 6d 69 6e 69 73 74 72 61 74 6f 72 20  e administrator 
c260: 72 75 6e 20 70 6f 6c 6c 20 2d 2d 63 68 65 63 6b  run poll --check
c270: 20 5c 22 61 66 74 65 72 20 74 68 65 20 68 6f 6f   \"after the hoo
c280: 6b 27 73 20 6c 6f 67 20 73 68 6f 77 73 20 61 20  k's log shows a 
c290: 72 75 6e 20 74 68 61 74 20 66 61 69 6c 65 64 5c  run that failed\
c2a0: 22 2e 20 48 65 72 65 20 74 68 65 20 6c 6f 67 20  ". Here the log 
c2b0: 73 68 6f 77 73 20 6e 6f 74 68 69 6e 67 2c 20 73  shows nothing, s
c2c0: 6f 20 61 20 66 61 69 6c 65 64 20 72 6f 75 6e 64  o a failed round
c2d0: 20 6e 65 65 64 73 20 61 20 6c 6f 67 20 6c 69 6e   needs a log lin
c2e0: 65 2c 20 61 6e 64 20 74 68 65 20 63 68 65 63 6b  e, and the check
c2f0: 20 6e 65 65 64 73 20 74 6f 20 73 65 65 20 74 68   needs to see th
c300: 65 20 72 65 70 6f 72 74 20 61 6c 72 65 61 64 79  e report already
c310: 20 77 72 69 74 74 65 6e 2e 22 2c 0a 20 20 20 22   written.",.   "
c320: 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f  code": "src/ocx/
c330: 6e 6f 64 65 2e 63 72 3a 33 33 31 2d 33 34 35 20  node.cr:331-345 
c340: 28 4e 6f 64 65 2e 72 65 70 6f 72 74 29 20 61 6e  (Node.report) an
c350: 64 20 3a 33 30 35 2d 33 31 33 20 28 4e 6f 64 65  d :305-313 (Node
c360: 2e 72 65 70 6c 79 29 20 77 72 69 74 65 20 74 68  .reply) write th
c370: 72 6f 75 67 68 20 50 6c 61 63 65 23 72 65 70 6c  rough Place#repl
c380: 79 2c 20 77 68 69 63 68 20 72 65 61 63 68 65 73  y, which reaches
c390: 20 74 68 65 20 73 70 6c 69 74 20 70 75 74 5f 70   the split put_p
c3a0: 6f 73 74 20 61 74 20 73 72 63 2f 6f 63 78 2f 66  ost at src/ocx/f
c3b0: 6f 73 73 69 6c 2f 66 6f 72 75 6d 2e 63 72 3a 39  ossil/forum.cr:9
c3c0: 35 2d 31 31 31 20 28 76 69 61 20 63 68 65 63 6b  5-111 (via check
c3d0: 65 64 5f 6f 75 74 2c 20 73 69 6e 63 65 20 74 68  ed_out, since th
c3e0: 65 20 70 6c 61 63 65 20 6e 61 6d 65 73 20 69 74  e place names it
c3f0: 73 20 72 65 70 6f 73 69 74 6f 72 79 29 2e 20 73  s repository). s
c400: 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f  rc/ocx/commands/
c410: 70 6f 6c 6c 2e 63 72 3a 31 39 36 2d 32 30 31 3a  poll.cr:196-201:
c420: 20 74 68 65 20 70 75 6c 6c 20 28 50 75 6c 6c 46   the pull (PullF
c430: 72 6f 6d 53 65 72 76 65 72 29 20 61 6e 64 20 41  romServer) and A
c440: 63 74 41 73 4e 6f 64 65 20 72 75 6e 20 69 6e 20  ctAsNode run in 
c450: 73 65 71 75 65 6e 63 65 2c 20 61 6e 64 20 6e 6f  sequence, and no
c460: 74 68 69 6e 67 20 6b 65 65 70 73 20 77 68 61 74  thing keeps what
c470: 20 77 61 73 20 70 75 6c 6c 65 64 20 77 68 65 6e   was pulled when
c480: 20 41 63 74 41 73 4e 6f 64 65 20 72 61 69 73 65   ActAsNode raise
c490: 73 2e 20 70 6f 6c 6c 2e 63 72 3a 38 33 2d 38 37  s. poll.cr:83-87
c4a0: 3a 20 74 68 65 20 48 6f 6f 6b 3a 3a 52 75 6e 20  : the Hook::Run 
c4b0: 6c 69 6e 65 20 69 73 20 61 70 70 65 6e 64 65 64  line is appended
c4c0: 20 6f 6e 6c 79 20 61 66 74 65 72 20 61 20 72 6f   only after a ro
c4d0: 75 6e 64 20 73 75 63 63 65 65 64 73 2e 22 0a 20  und succeeds.". 
c4e0: 20 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c   },.  {.   "titl
c4f0: 65 22 3a 20 22 57 72 69 74 65 72 73 20 77 61 69  e": "Writers wai
c500: 74 69 6e 67 20 66 6f 72 20 4f 43 58 27 73 20 74  ting for OCX's t
c510: 75 72 6e 20 70 6f 6c 6c 20 65 76 65 72 79 20 31  urn poll every 1
c520: 30 30 20 6d 73 20 69 6e 73 74 65 61 64 20 6f 66  00 ms instead of
c530: 20 71 75 65 75 69 6e 67 2c 20 73 6f 20 61 20 77   queuing, so a w
c540: 72 69 74 65 72 20 74 68 61 74 20 74 61 6b 65 73  riter that takes
c550: 20 74 68 65 20 74 75 72 6e 20 61 67 61 69 6e 20   the turn again 
c560: 77 69 6e 73 20 65 76 65 72 79 20 74 69 6d 65 22  wins every time"
c570: 2c 0a 20 20 20 22 73 65 76 65 72 69 74 79 22 3a  ,.   "severity":
c580: 20 22 6c 6f 77 22 2c 0a 20 20 20 22 72 65 70 72   "low",.   "repr
c590: 6f 64 75 63 74 69 6f 6e 22 3a 20 22 53 61 6d 65  oduction": "Same
c5a0: 20 73 65 74 75 70 2e 20 53 63 72 69 70 74 20 24   setup. Script $
c5b0: 44 2f 74 48 2e 73 68 2c 20 77 69 74 68 6f 75 74  D/tH.sh, without
c5c0: 20 69 74 73 20 2f 70 72 6f 63 2f 6c 6f 63 6b 73   its /proc/locks
c5d0: 20 77 61 69 74 2c 20 77 68 69 63 68 20 6e 65 76   wait, which nev
c5e0: 65 72 20 6d 61 74 63 68 65 73 20 62 65 63 61 75  er matches becau
c5f0: 73 65 20 74 68 65 20 77 61 69 74 65 72 20 64 6f  se the waiter do
c600: 65 73 20 6e 6f 74 20 62 6c 6f 63 6b 20 69 6e 20  es not block in 
c610: 74 68 65 20 6b 65 72 6e 65 6c 3a 20 28 31 29 20  the kernel: (1) 
c620: 3a 20 3e 20 24 44 2f 63 74 6c 2f 63 61 6c 6c 73  : > $D/ctl/calls
c630: 2e 6c 6f 67 3b 20 24 44 2f 67 61 74 65 2e 73 68  .log; $D/gate.sh
c640: 20 61 72 6d 20 74 65 73 74 2d 63 6f 6e 74 65 6e   arm test-conten
c650: 74 2d 70 75 74 2e 20 28 32 29 20 63 64 20 24 44  t-put. (2) cd $D
c660: 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74 72 65 65  /clones/ivy/tree
c670: 20 61 6e 64 20 73 74 61 72 74 20 77 72 69 74 65   and start write
c680: 72 31 20 69 6e 20 74 68 65 20 62 61 63 6b 67 72  r1 in the backgr
c690: 6f 75 6e 64 3a 20 50 41 54 48 3d 24 44 2f 73 68  ound: PATH=$D/sh
c6a0: 69 6d 3a 24 50 41 54 48 20 6e 69 63 65 20 6f 63  im:$PATH nice oc
c6b0: 78 32 20 2d 2d 6a 73 6f 6e 20 70 6f 73 74 20 64  x2 --json post d
c6c0: 36 37 37 35 37 30 36 20 5c 22 74 75 72 6e 20 48  6775706 \"turn H
c6d0: 31 5c 22 2e 20 28 33 29 20 24 44 2f 67 61 74 65  1\". (3) $D/gate
c6e0: 2e 73 68 20 77 61 69 74 20 74 65 73 74 2d 63 6f  .sh wait test-co
c6f0: 6e 74 65 6e 74 2d 70 75 74 2e 20 57 72 69 74 65  ntent-put. Write
c700: 72 31 20 6e 6f 77 20 68 6f 6c 64 73 20 63 6c 6f  r1 now holds clo
c710: 6e 65 2e 66 6f 73 73 69 6c 2d 6f 63 78 2e 6c 6f  ne.fossil-ocx.lo
c720: 63 6b 2e 20 28 34 29 20 53 74 61 72 74 20 77 72  ck. (4) Start wr
c730: 69 74 65 72 32 20 74 68 65 20 73 61 6d 65 20 77  iter2 the same w
c740: 61 79 20 77 69 74 68 20 5c 22 74 75 72 6e 20 48  ay with \"turn H
c750: 32 5c 22 2e 20 63 61 74 20 2f 70 72 6f 63 2f 3c  2\". cat /proc/<
c760: 77 72 69 74 65 72 32 3e 2f 77 63 68 61 6e 20 67  writer2>/wchan g
c770: 69 76 65 73 20 65 70 5f 70 6f 6c 6c 2c 20 77 72  ives ep_poll, wr
c780: 69 74 65 72 32 20 68 61 73 20 63 6c 6f 6e 65 2e  iter2 has clone.
c790: 66 6f 73 73 69 6c 2d 6f 63 78 2e 6c 6f 63 6b 20  fossil-ocx.lock 
c7a0: 6f 70 65 6e 20 61 73 20 66 64 20 38 2c 20 61 6e  open as fd 8, an
c7b0: 64 20 2f 70 72 6f 63 2f 6c 6f 63 6b 73 20 73 68  d /proc/locks sh
c7c0: 6f 77 73 20 6e 6f 20 77 61 69 74 65 72 2e 20 28  ows no waiter. (
c7d0: 35 29 20 24 44 2f 67 61 74 65 2e 73 68 20 6f 70  5) $D/gate.sh op
c7e0: 65 6e 20 74 65 73 74 2d 63 6f 6e 74 65 6e 74 2d  en test-content-
c7f0: 70 75 74 3b 20 24 44 2f 67 61 74 65 2e 73 68 20  put; $D/gate.sh 
c800: 77 61 69 74 20 74 65 73 74 2d 63 6f 6e 74 65 6e  wait test-conten
c810: 74 2d 70 75 74 3b 20 24 44 2f 67 61 74 65 2e 73  t-put; $D/gate.s
c820: 68 20 6f 70 65 6e 20 74 65 73 74 2d 63 6f 6e 74  h open test-cont
c830: 65 6e 74 2d 70 75 74 2e 20 28 36 29 20 63 75 74  ent-put. (6) cut
c840: 20 2d 64 27 20 27 20 2d 66 31 2d 33 20 24 44 2f   -d' ' -f1-3 $D/
c850: 63 74 6c 2f 63 61 6c 6c 73 2e 6c 6f 67 2e 22 2c  ctl/calls.log.",
c860: 0a 20 20 20 22 6f 62 73 65 72 76 65 64 22 3a 20  .   "observed": 
c870: 22 54 68 65 20 63 61 6c 6c 73 20 6c 6f 67 20 73  "The calls log s
c880: 68 6f 77 73 20 77 72 69 74 65 72 31 27 73 20 74  hows writer1's t
c890: 65 73 74 2d 63 6f 6e 74 65 6e 74 2d 70 75 74 2c  est-content-put,
c8a0: 20 74 68 65 6e 20 77 72 69 74 65 72 31 27 73 20   then writer1's 
c8b0: 74 65 73 74 2d 63 72 6f 73 73 6c 69 6e 6b 20 61  test-crosslink a
c8c0: 6e 64 20 70 75 73 68 2c 20 61 6e 64 20 6f 6e 6c  nd push, and onl
c8d0: 79 20 74 68 65 6e 20 77 72 69 74 65 72 32 27 73  y then writer2's
c8e0: 20 66 69 72 73 74 20 63 6f 6d 6d 61 6e 64 2c 20   first command, 
c8f0: 75 73 65 72 20 64 65 66 61 75 6c 74 2e 20 57 72  user default. Wr
c900: 69 74 65 72 32 20 68 61 64 20 62 65 65 6e 20 77  iter2 had been w
c910: 61 69 74 69 6e 67 20 73 69 6e 63 65 20 62 65 66  aiting since bef
c920: 6f 72 65 20 77 72 69 74 65 72 31 27 73 20 73 65  ore writer1's se
c930: 63 6f 6e 64 20 63 6f 6d 6d 61 6e 64 2c 20 61 6e  cond command, an
c940: 64 20 77 72 69 74 65 72 31 20 74 6f 6f 6b 20 74  d writer1 took t
c950: 68 65 20 74 75 72 6e 20 74 77 69 63 65 20 6d 6f  he turn twice mo
c960: 72 65 20 61 68 65 61 64 20 6f 66 20 69 74 2e 20  re ahead of it. 
c970: 42 6f 74 68 20 70 6f 73 74 73 20 65 6e 64 65 64  Both posts ended
c980: 20 6f 6b 20 28 39 30 66 62 31 32 30 63 e2 80 a6   ok (90fb120c…
c990: 2c 20 61 65 35 65 66 34 61 33 e2 80 a6 29 2c 20  , ae5ef4a3…), 
c9a0: 73 6f 20 6d 75 74 75 61 6c 20 65 78 63 6c 75 73  so mutual exclus
c9b0: 69 6f 6e 20 68 65 6c 64 2e 20 43 72 79 73 74 61  ion held. Crysta
c9c0: 6c 20 31 2e 31 38 27 73 20 46 69 6c 65 23 66 6c  l 1.18's File#fl
c9d0: 6f 63 6b 5f 65 78 63 6c 75 73 69 76 65 20 69 73  ock_exclusive is
c9e0: 20 60 75 6e 74 69 6c 20 66 6c 6f 63 6b 28 6f 70   `until flock(op
c9f0: 7c 4e 42 29 3b 20 73 6c 65 65 70 20 30 2e 31 2e  |NB); sleep 0.1.
ca00: 73 65 63 6f 6e 64 73 3b 20 65 6e 64 60 20 28 2f  seconds; end` (/
ca10: 75 73 72 2f 6c 69 62 2f 63 72 79 73 74 61 6c 2f  usr/lib/crystal/
ca20: 63 6f 72 65 2f 63 72 79 73 74 61 6c 2f 73 79 73  core/crystal/sys
ca30: 74 65 6d 2f 75 6e 69 78 2f 66 69 6c 65 5f 64 65  tem/unix/file_de
ca40: 73 63 72 69 70 74 6f 72 2e 63 72 3a 31 38 35 2d  scriptor.cr:185-
ca50: 31 39 32 29 2e 22 2c 0a 20 20 20 22 65 78 70 65  192).",.   "expe
ca60: 63 74 65 64 22 3a 20 22 64 6f 63 73 2f 70 72 6f  cted": "docs/pro
ca70: 74 6f 63 6f 6c 2d 76 32 2d 64 72 61 66 74 2d 6f  tocol-v2-draft-o
ca80: 77 6e 65 72 2e 6d 64 3a 20 5c 22 41 20 74 6f 6f  wner.md: \"A too
ca90: 6c 20 77 61 69 74 73 20 66 6f 72 20 69 74 73 20  l waits for its 
caa0: 74 75 72 6e 20 61 74 20 66 6f 73 73 69 6c 20 69  turn at fossil i
cab0: 6e 20 74 68 65 20 6b 65 72 6e 65 6c 20 28 66 6c  n the kernel (fl
cac0: 6f 63 6b 20 77 69 74 68 6f 75 74 20 4c 4f 43 4b  ock without LOCK
cad0: 5f 4e 42 29 2c 20 6e 65 76 65 72 20 62 79 20 43  _NB), never by C
cae0: 72 79 73 74 61 6c 27 73 20 60 66 6c 6f 63 6b 5f  rystal's `flock_
caf0: 65 78 63 6c 75 73 69 76 65 60 2c 20 77 68 69 63  exclusive`, whic
cb00: 68 20 73 6c 65 65 70 73 20 61 20 74 65 6e 74 68  h sleeps a tenth
cb10: 20 6f 66 20 61 20 73 65 63 6f 6e 64 20 61 6e 64   of a second and
cb20: 20 74 72 69 65 73 20 61 67 61 69 6e 2e 5c 22 22   tries again.\""
cb30: 2c 0a 20 20 20 22 63 6f 64 65 22 3a 20 22 73 72  ,.   "code": "sr
cb40: 63 2f 6f 63 78 2f 66 6f 73 73 69 6c 2e 63 72 3a  c/ocx/fossil.cr:
cb50: 31 35 32 2d 31 35 39 20 28 46 6f 73 73 69 6c 2e  152-159 (Fossil.
cb60: 74 75 72 6e 2c 20 6c 6f 63 6b 2e 66 6c 6f 63 6b  turn, lock.flock
cb70: 5f 65 78 63 6c 75 73 69 76 65 29 2e 20 54 68 65  _exclusive). The
cb80: 20 73 61 6d 65 20 63 61 6c 6c 20 69 73 20 69 6e   same call is in
cb90: 20 73 72 63 2f 6f 63 78 2f 63 61 72 65 2e 63 72   src/ocx/care.cr
cba0: 3a 33 36 2d 34 31 20 28 4e 6f 64 65 2e 68 65 6c  :36-41 (Node.hel
cbb0: 64 2c 20 66 6f 72 20 72 6f 75 6e 64 2e 6c 6f 63  d, for round.loc
cbc0: 6b 20 61 6e 64 20 70 6f 6c 6c 2e 6c 6f 63 6b 29  k and poll.lock)
cbd0: 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22  .".  },.  {.   "
cbe0: 74 69 74 6c 65 22 3a 20 22 4f 43 58 27 73 20 74  title": "OCX's t
cbf0: 75 72 6e 20 69 73 20 68 65 6c 64 20 74 68 72 6f  urn is held thro
cc00: 75 67 68 20 46 6f 73 73 69 6c 27 73 20 31 35 2d  ugh Fossil's 15-
cc10: 73 65 63 6f 6e 64 20 62 75 73 79 20 77 61 69 74  second busy wait
cc20: 2c 20 73 6f 20 75 6e 64 65 72 20 61 6e 20 6f 75  , so under an ou
cc30: 74 73 69 64 65 20 6c 6f 63 6b 20 4e 20 70 61 72  tside lock N par
cc40: 61 6c 6c 65 6c 20 77 65 62 20 77 72 69 74 65 73  allel web writes
cc50: 20 61 6e 73 77 65 72 20 61 74 20 31 35 2c 20 33   answer at 15, 3
cc60: 30 2c 20 34 35 20 e2 80 a6 20 73 65 63 6f 6e 64  0, 45 … second
cc70: 73 22 2c 0a 20 20 20 22 73 65 76 65 72 69 74 79  s",.   "severity
cc80: 22 3a 20 22 6c 6f 77 22 2c 0a 20 20 20 22 72 65  ": "low",.   "re
cc90: 70 72 6f 64 75 63 74 69 6f 6e 22 3a 20 22 53 61  production": "Sa
cca0: 6d 65 20 73 65 74 75 70 2c 20 77 69 74 68 20 6f  me setup, with o
ccb0: 77 6e 65 72 20 73 69 67 6e 65 64 20 69 6e 3a 20  wner signed in: 
ccc0: 63 75 72 6c 20 2d 63 20 24 44 2f 63 74 6c 2f 6a  curl -c $D/ctl/j
ccd0: 61 72 2d 6f 77 6e 65 72 20 2d 2d 64 61 74 61 2d  ar-owner --data-
cce0: 75 72 6c 65 6e 63 6f 64 65 20 75 3d 6f 77 6e 65  urlencode u=owne
ccf0: 72 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63 6f  r --data-urlenco
cd00: 64 65 20 70 3d 3c 73 63 72 61 74 63 68 20 70 77  de p=<scratch pw
cd10: 20 66 72 6f 6d 20 70 61 73 73 77 6f 72 64 73 2e   from passwords.
cd20: 74 78 74 3e 20 2d 64 20 69 6e 3d 31 20 24 55 52  txt> -d in=1 $UR
cd30: 4c 2f 6c 6f 67 69 6e 2e 20 53 63 72 69 70 74 20  L/login. Script 
cd40: 24 44 2f 74 4d 2e 73 68 3a 20 73 71 6c 69 74 65  $D/tM.sh: sqlite
cd50: 33 20 24 52 45 50 4f 20 74 61 6b 65 73 20 42 45  3 $REPO takes BE
cd60: 47 49 4e 20 49 4d 4d 45 44 49 41 54 45 2e 20 54  GIN IMMEDIATE. T
cd70: 68 65 6e 20 33 20 63 75 72 6c 73 20 61 72 65 20  hen 3 curls are 
cd80: 72 65 6c 65 61 73 65 64 20 74 6f 67 65 74 68 65  released togethe
cd90: 72 20 66 72 6f 6d 20 61 20 66 6c 6f 63 6b 20 62  r from a flock b
cda0: 61 72 72 69 65 72 3a 20 63 75 72 6c 20 2d 73 20  arrier: curl -s 
cdb0: 2d 62 20 24 44 2f 63 74 6c 2f 6a 61 72 2d 6f 77  -b $D/ctl/jar-ow
cdc0: 6e 65 72 20 2d 65 20 5c 22 24 55 52 4c 2f 65 78  ner -e \"$URL/ex
cdd0: 74 2f 6f 63 78 32 2d 63 67 69 5c 22 20 2d 2d 64  t/ocx2-cgi\" --d
cde0: 61 74 61 2d 75 72 6c 65 6e 63 6f 64 65 20 5c 22  ata-urlencode \"
cdf0: 6f 62 6a 65 63 74 69 76 65 3d 43 47 49 20 72 75  objective=CGI ru
ce00: 6e 20 4d 3c 69 3e 20 75 6e 64 65 72 20 6f 75 74  n M<i> under out
ce10: 73 69 64 65 20 6c 6f 63 6b 5c 22 20 2d 64 20 6e  side lock\" -d n
ce20: 6f 64 65 3d 6e 6f 64 65 41 20 2d 2d 64 61 74 61  ode=nodeA --data
ce30: 2d 75 72 6c 65 6e 63 6f 64 65 20 27 66 69 65 6c  -urlencode 'fiel
ce40: 64 73 3d 7b 5c 22 70 72 6f 63 65 73 73 5c 22 3a  ds={\"process\":
ce50: 7b 5c 22 75 73 65 72 5c 22 3a 5c 22 6f 74 74 6f  {\"user\":\"otto
ce60: 5c 22 2c 5c 22 63 6f 6d 6d 61 6e 64 5c 22 3a 5b  \",\"command\":[
ce70: 5c 22 74 72 75 65 5c 22 5d 7d 7d 27 20 5c 22 24  \"true\"]}}' \"$
ce80: 55 52 4c 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69  URL/ext/ocx2-cgi
ce90: 2f 63 72 65 61 74 65 3f 6a 73 6f 6e 3d 6f 6e 5c  /create?json=on\
cea0: 22 20 2d 77 20 27 25 7b 68 74 74 70 5f 63 6f 64  " -w '%{http_cod
ceb0: 65 7d 20 25 7b 74 69 6d 65 5f 74 6f 74 61 6c 7d  e} %{time_total}
cec0: 27 2e 20 54 6f 20 63 68 65 63 6b 20 77 68 69 63  '. To check whic
ced0: 68 20 63 6f 6d 6d 61 6e 64 20 77 61 69 74 73 2c  h command waits,
cee0: 20 24 44 2f 74 4a 32 2e 73 68 20 74 69 6d 65 73   $D/tJ2.sh times
cef0: 20 61 20 62 61 72 65 20 66 6f 73 73 69 6c 20 6f   a bare fossil o
cf00: 70 65 6e 20 2d 2d 65 6d 70 74 79 20 61 6e 64 20  pen --empty and 
cf10: 66 6f 73 73 69 6c 20 63 6c 6f 73 65 20 75 6e 64  fossil close und
cf20: 65 72 20 74 68 65 20 73 61 6d 65 20 68 6f 6c 64  er the same hold
cf30: 2e 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65 64  .",.   "observed
cf40: 22 3a 20 22 54 68 65 20 74 68 72 65 65 20 61 6e  ": "The three an
cf50: 73 77 65 72 65 64 20 48 54 54 50 20 34 30 33 20  swered HTTP 403 
cf60: 61 74 20 31 35 2e 30 37 20 73 2c 20 33 30 2e 31  at 15.07 s, 30.1
cf70: 38 20 73 20 61 6e 64 20 34 35 2e 32 39 20 73 2e  8 s and 45.29 s.
cf80: 20 45 61 63 68 20 73 74 6f 70 70 65 64 20 6f 6e   Each stopped on
cf90: 20 74 65 73 74 2d 63 6f 6e 74 65 6e 74 2d 70 75   test-content-pu
cfa0: 74 20 28 6c 6f 63 6b 65 64 29 20 61 6e 64 20 74  t (locked) and t
cfb0: 68 65 6e 20 74 68 65 20 63 6c 6f 73 65 20 28 6c  hen the close (l
cfc0: 6f 63 6b 65 64 29 2c 20 61 6e 64 20 6e 6f 74 68  ocked), and noth
cfd0: 69 6e 67 20 77 61 73 20 77 72 69 74 74 65 6e 20  ing was written 
cfe0: 28 6d 61 78 20 72 69 64 20 75 6e 63 68 61 6e 67  (max rid unchang
cff0: 65 64 29 2e 20 49 6e 20 74 4a 32 2e 73 68 2c 20  ed). In tJ2.sh, 
d000: 66 6f 73 73 69 6c 20 6f 70 65 6e 20 74 6f 6f 6b  fossil open took
d010: 20 30 2e 30 30 37 20 73 20 61 6e 64 20 66 6f 73   0.007 s and fos
d020: 73 69 6c 20 63 6c 6f 73 65 20 74 6f 6f 6b 20 31  sil close took 1
d030: 35 2e 30 33 20 73 2c 20 74 68 65 6e 20 70 72 69  5.03 s, then pri
d040: 6e 74 65 64 20 27 64 61 74 61 62 61 73 65 20 69  nted 'database i
d050: 73 20 6c 6f 63 6b 65 64 3a 20 7b 44 45 4c 45 54  s locked: {DELET
d060: 45 20 46 52 4f 4d 20 63 6f 6e 66 69 67 20 57 48  E FROM config WH
d070: 45 52 45 20 6e 61 6d 65 3d 27 63 6b 6f 75 74 3a  ERE name='ckout:
d080: e2 80 a6 27 7d 27 2e 20 45 61 63 68 20 4f 43 58  …'}'. Each OCX
d090: 20 63 6c 6f 73 65 20 73 69 74 73 20 69 6e 20 46   close sits in F
d0a0: 6f 73 73 69 6c 27 73 20 62 75 73 79 20 77 61 69  ossil's busy wai
d0b0: 74 20 77 68 69 6c 65 20 68 6f 6c 64 69 6e 67 20  t while holding 
d0c0: 4f 43 58 27 73 20 74 75 72 6e 2c 20 73 6f 20 65  OCX's turn, so e
d0d0: 61 63 68 20 72 65 71 75 65 73 74 20 77 61 69 74  ach request wait
d0e0: 73 20 66 6f 72 20 65 76 65 72 79 20 6f 6e 65 20  s for every one 
d0f0: 61 68 65 61 64 20 6f 66 20 69 74 2e 22 2c 0a 20  ahead of it.",. 
d100: 20 20 22 65 78 70 65 63 74 65 64 22 3a 20 22 41    "expected": "A
d110: 6e 20 6f 75 74 73 69 64 65 20 77 72 69 74 65 72  n outside writer
d120: 27 73 20 6c 6f 63 6b 20 73 68 6f 75 6c 64 20 62  's lock should b
d130: 65 20 72 65 70 6f 72 74 65 64 20 70 72 6f 6d 70  e reported promp
d140: 74 6c 79 20 74 6f 20 65 61 63 68 20 63 61 6c 6c  tly to each call
d150: 65 72 2e 20 54 68 65 20 76 32 20 64 72 61 66 74  er. The v2 draft
d160: 20 28 64 6f 63 73 2f 70 72 6f 74 6f 63 6f 6c 2d   (docs/protocol-
d170: 76 32 2d 64 72 61 66 74 2d 6f 77 6e 65 72 2e 6d  v2-draft-owner.m
d180: 64 29 20 73 61 79 73 20 61 20 77 72 69 74 65 20  d) says a write 
d190: 74 68 61 74 20 6d 65 65 74 73 20 6f 6e 65 20 69  that meets one i
d1a0: 73 20 74 72 69 65 64 20 61 67 61 69 6e 20 61 66  s tried again af
d1b0: 74 65 72 20 4f 43 58 27 73 20 62 75 73 79 20 74  ter OCX's busy t
d1c0: 69 6d 65 6f 75 74 2e 20 49 74 20 64 6f 65 73 20  imeout. It does 
d1d0: 6e 6f 74 20 73 61 79 20 74 68 61 74 20 63 61 6c  not say that cal
d1e0: 6c 65 72 73 20 71 75 65 75 65 20 62 65 68 69 6e  lers queue behin
d1f0: 64 20 6f 6e 65 20 61 6e 6f 74 68 65 72 27 73 20  d one another's 
d200: 74 69 6d 65 6f 75 74 73 2e 22 2c 0a 20 20 20 22  timeouts.",.   "
d210: 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f  code": "src/ocx/
d220: 66 6f 73 73 69 6c 2e 63 72 3a 32 34 34 3a 20 46  fossil.cr:244: F
d230: 6f 73 73 69 6c 2e 74 75 72 6e 20 77 72 61 70 73  ossil.turn wraps
d240: 20 74 68 65 20 77 68 6f 6c 65 20 68 6f 73 74 65   the whole hoste
d250: 64 20 66 6f 73 73 69 6c 20 70 72 6f 63 65 73 73  d fossil process
d260: 2c 20 69 6e 63 6c 75 64 69 6e 67 20 69 74 73 20  , including its 
d270: 53 51 4c 69 74 65 20 62 75 73 79 20 77 61 69 74  SQLite busy wait
d280: 2e 20 73 72 63 2f 6f 63 78 2f 66 6f 73 73 69 6c  . src/ocx/fossil
d290: 2f 73 79 6e 63 2e 63 72 3a 32 34 34 2d 32 35 32  /sync.cr:244-252
d2a0: 20 28 63 68 65 63 6b 65 64 5f 6f 75 74 29 20 61   (checked_out) a
d2b0: 6c 77 61 79 73 20 72 75 6e 73 20 63 6c 6f 73 65  lways runs close
d2c0: 20 61 66 74 65 72 20 61 20 66 61 69 6c 65 64 20   after a failed 
d2d0: 70 75 74 2c 20 61 6e 64 20 74 68 61 74 20 63 6c  put, and that cl
d2e0: 6f 73 65 20 77 61 69 74 73 20 74 68 65 20 66 75  ose waits the fu
d2f0: 6c 6c 20 31 35 20 73 2e 22 0a 20 20 7d 2c 0a 20  ll 15 s.".  },. 
d300: 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a 20 22   {.   "title": "
d310: 54 68 65 20 74 75 72 6e 20 6c 6f 63 6b 20 63 72  The turn lock cr
d320: 65 61 74 65 73 20 61 20 73 74 72 61 79 20 27 3c  eates a stray '<
d330: 70 61 74 68 3e 2d 6f 63 78 2e 6c 6f 63 6b 27 20  path>-ocx.lock' 
d340: 66 69 6c 65 20 62 65 73 69 64 65 20 61 20 72 65  file beside a re
d350: 70 6f 73 69 74 6f 72 79 20 74 68 61 74 20 64 6f  pository that do
d360: 65 73 20 6e 6f 74 20 65 78 69 73 74 2c 20 65 76  es not exist, ev
d370: 65 6e 20 66 6f 72 20 61 20 72 65 66 75 73 65 64  en for a refused
d380: 20 72 65 61 64 22 2c 0a 20 20 20 22 73 65 76 65   read",.   "seve
d390: 72 69 74 79 22 3a 20 22 6c 6f 77 22 2c 0a 20 20  rity": "low",.  
d3a0: 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a   "reproduction":
d3b0: 20 22 53 61 6d 65 20 65 6e 76 2e 20 6d 6b 64 69   "Same env. mkdi
d3c0: 72 20 2d 70 20 24 44 2f 63 74 6c 2f 74 79 70 6f  r -p $D/ctl/typo
d3d0: 3b 20 63 64 20 24 44 2f 63 74 6c 2f 74 79 70 6f  ; cd $D/ctl/typo
d3e0: 3b 20 6e 69 63 65 20 6f 63 78 32 20 2d 2d 6a 73  ; nice ocx2 --js
d3f0: 6f 6e 20 2d 2d 72 65 70 6f 73 69 74 6f 72 79 20  on --repository 
d400: 24 44 2f 63 74 6c 2f 74 79 70 6f 2f 6e 6f 70 65  $D/ctl/typo/nope
d410: 2e 66 6f 73 73 69 6c 20 2d 2d 75 73 65 72 20 6f  .fossil --user o
d420: 77 6e 65 72 20 74 68 72 65 61 64 20 61 62 63 64  wner thread abcd
d430: 3b 20 6c 73 20 2d 6c 61 20 24 44 2f 63 74 6c 2f  ; ls -la $D/ctl/
d440: 74 79 70 6f 22 2c 0a 20 20 20 22 6f 62 73 65 72  typo",.   "obser
d450: 76 65 64 22 3a 20 22 54 68 65 20 61 6e 73 77 65  ved": "The answe
d460: 72 20 77 61 73 20 6f 6b 3a 66 61 6c 73 65 2c 20  r was ok:false, 
d470: 5c 22 6f 77 6e 65 72 20 6c 61 63 6b 73 20 77 68  \"owner lacks wh
d480: 61 74 20 74 68 72 65 61 64 20 6e 65 65 64 73 3a  at thread needs:
d490: 20 61 6e 79 20 6f 66 20 74 68 65 20 46 6f 73 73   any of the Foss
d4a0: 69 6c 20 63 61 70 61 62 69 6c 69 74 69 65 73 20  il capabilities 
d4b0: 6f 20 28 63 68 65 63 6b 2d 6f 75 74 29 3b 20 69  o (check-out); i
d4c0: 74 20 68 6f 6c 64 73 20 6e 6f 6e 65 5c 22 2c 20  t holds none\", 
d4d0: 79 65 74 20 24 44 2f 63 74 6c 2f 74 79 70 6f 2f  yet $D/ctl/typo/
d4e0: 6e 6f 70 65 2e 66 6f 73 73 69 6c 2d 6f 63 78 2e  nope.fossil-ocx.
d4f0: 6c 6f 63 6b 20 28 30 20 62 79 74 65 73 29 20 6e  lock (0 bytes) n
d500: 6f 77 20 65 78 69 73 74 73 2e 20 54 68 65 20 66  ow exists. The f
d510: 69 72 73 74 20 70 6f 6c 6c 20 2d 2d 6c 6f 67 69  irst poll --logi
d520: 6e 20 6e 6f 64 65 61 20 6c 69 6b 65 77 69 73 65  n nodea likewise
d530: 20 6c 65 66 74 20 6e 6f 64 65 2f 63 6c 6f 6e 65   left node/clone
d540: 2e 66 6f 73 73 69 6c 2d 6f 63 78 2e 6c 6f 63 6b  .fossil-ocx.lock
d550: 20 62 65 66 6f 72 65 20 61 6e 79 20 63 6c 6f 6e   before any clon
d560: 65 20 65 78 69 73 74 65 64 2c 20 61 6e 64 20 2f  e existed, and /
d570: 74 6d 70 20 68 6f 6c 64 73 20 6f 74 68 65 72 73  tmp holds others
d580: 27 20 27 e2 80 a6 6f 63 78 2d 6d 69 73 73 69 6e  ' '…ocx-missin
d590: 67 2d 6f 63 78 2e 6c 6f 63 6b 27 20 66 69 6c 65  g-ocx.lock' file
d5a0: 73 20 66 72 6f 6d 20 74 68 65 20 73 61 6d 65 20  s from the same 
d5b0: 63 61 75 73 65 2e 22 2c 0a 20 20 20 22 65 78 70  cause.",.   "exp
d5c0: 65 63 74 65 64 22 3a 20 22 41 20 72 65 66 75 73  ected": "A refus
d5d0: 65 64 20 63 61 6c 6c 20 74 68 61 74 20 72 65 61  ed call that rea
d5e0: 64 73 20 6e 6f 74 68 69 6e 67 20 73 68 6f 75 6c  ds nothing shoul
d5f0: 64 20 77 72 69 74 65 20 6e 6f 74 68 69 6e 67 20  d write nothing 
d600: 6f 6e 20 74 68 65 20 68 6f 73 74 2e 20 41 20 6c  on the host. A l
d610: 6f 63 6b 20 66 69 6c 65 20 69 73 20 6f 6e 6c 79  ock file is only
d620: 20 6e 65 65 64 65 64 20 62 65 73 69 64 65 20 61   needed beside a
d630: 20 72 65 70 6f 73 69 74 6f 72 79 20 74 68 61 74   repository that
d640: 20 66 6f 73 73 69 6c 20 77 69 6c 6c 20 61 63 74   fossil will act
d650: 75 61 6c 6c 79 20 6f 70 65 6e 2e 22 2c 0a 20 20  ually open.",.  
d660: 20 22 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63   "code": "src/oc
d670: 78 2f 66 6f 73 73 69 6c 2e 63 72 3a 31 35 34 2d  x/fossil.cr:154-
d680: 31 35 35 3a 20 46 69 6c 65 2e 65 78 69 73 74 73  155: File.exists
d690: 3f 20 66 61 6c 6c 73 20 62 61 63 6b 20 74 6f 20  ? falls back to 
d6a0: 46 69 6c 65 2e 65 78 70 61 6e 64 5f 70 61 74 68  File.expand_path
d6b0: 2c 20 61 6e 64 20 74 68 65 6e 20 46 69 6c 65 2e  , and then File.
d6c0: 6f 70 65 6e 28 6e 61 6d 65 64 20 2b 20 54 55 52  open(named + TUR
d6d0: 4e 2c 20 5c 22 61 5c 22 29 20 63 72 65 61 74 65  N, \"a\") create
d6e0: 73 20 74 68 65 20 66 69 6c 65 20 77 68 65 74 68  s the file wheth
d6f0: 65 72 20 6f 72 20 6e 6f 74 20 74 68 65 20 72 65  er or not the re
d700: 70 6f 73 69 74 6f 72 79 20 65 78 69 73 74 73 2e  pository exists.
d710: 22 0a 20 20 7d 0a 20 5d 2c 0a 20 22 74 72 69 65  ".  }. ],. "trie
d720: 64 22 3a 20 22 41 6c 6c 20 74 65 73 74 73 20 72  d": "All tests r
d730: 61 6e 20 6f 6e 20 61 20 66 72 65 73 68 20 69 6e  an on a fresh in
d740: 73 74 61 6e 63 65 3a 20 73 65 74 75 70 2e 73 68  stance: setup.sh
d750: 20 2e 2e 2e 2f 61 64 76 65 72 73 61 72 79 2f 63   .../adversary/c
d760: 6f 6e 63 75 72 72 65 6e 63 79 20 31 38 39 33 34  oncurrency 18934
d770: 2e 20 54 68 65 79 20 72 61 6e 20 66 72 6f 6d 20  . They ran from 
d780: 73 63 72 69 70 74 73 20 74 41 e2 80 93 74 50 2e  scripts tA–tP.
d790: 73 68 20 69 6e 20 74 68 61 74 20 64 69 72 65 63  sh in that direc
d7a0: 74 6f 72 79 2c 20 77 69 74 68 20 6f 72 64 65 72  tory, with order
d7b0: 69 6e 67 73 20 66 6f 72 63 65 64 20 62 79 20 61  ings forced by a
d7c0: 20 66 6f 73 73 69 6c 20 73 68 69 6d 20 67 61 74   fossil shim gat
d7d0: 65 64 20 6f 6e 20 66 69 66 6f 73 20 28 73 68 69  ed on fifos (shi
d7e0: 6d 2f 66 6f 73 73 69 6c 2c 20 67 61 74 65 2e 73  m/fossil, gate.s
d7f0: 68 29 2c 20 66 6c 6f 63 6b 20 62 61 72 72 69 65  h), flock barrie
d800: 72 73 2c 20 61 6e 64 20 61 20 73 71 6c 69 74 65  rs, and a sqlite
d810: 33 20 43 4c 49 20 68 6f 6c 64 69 6e 67 20 42 45  3 CLI holding BE
d820: 47 49 4e 20 49 4d 4d 45 44 49 41 54 45 20 28 68  GIN IMMEDIATE (h
d830: 6f 6c 64 2e 73 68 29 2e 20 4e 6f 74 68 69 6e 67  old.sh). Nothing
d840: 20 77 61 73 20 6f 72 64 65 72 65 64 20 62 79 20   was ordered by 
d850: 73 6c 65 65 70 73 2e 20 54 68 65 20 73 65 72 76  sleeps. The serv
d860: 65 72 20 77 61 73 20 73 74 6f 70 70 65 64 20 77  er was stopped w
d870: 69 74 68 20 73 74 6f 70 2e 73 68 20 61 74 20 74  ith stop.sh at t
d880: 68 65 20 65 6e 64 20 28 27 73 74 6f 70 70 65 64  he end ('stopped
d890: 3a 20 6e 6f 74 68 69 6e 67 20 73 65 72 76 65 73  : nothing serves
d8a0: 20 e2 80 a6 27 3b 20 63 75 72 6c 20 74 6f 20 31   …'; curl to 1
d8b0: 38 39 33 34 20 65 78 69 74 73 20 37 29 2e 20 54  8934 exits 7). T
d8c0: 68 65 73 65 20 68 65 6c 64 3a 5c 6e 28 31 29 20  hese held:\n(1) 
d8d0: 42 75 72 73 74 20 74 47 2e 73 68 2e 20 31 37 20  Burst tG.sh. 17 
d8e0: 4f 43 58 20 77 72 69 74 65 72 73 20 73 74 61 72  OCX writers star
d8f0: 74 65 64 20 74 6f 67 65 74 68 65 72 20 66 72 6f  ted together fro
d900: 6d 20 6f 6e 65 20 62 61 72 72 69 65 72 3a 20 33  m one barrier: 3
d910: 20 43 4c 49 20 63 72 65 61 74 65 73 20 28 6f 77   CLI creates (ow
d920: 6e 65 72 2c 20 73 61 6c 6c 79 2c 20 61 64 61 6d  ner, sally, adam
d930: 29 20 61 6e 64 20 32 20 63 72 65 61 74 65 73 20  ) and 2 creates 
d940: 6f 6e 20 74 69 63 6b 65 74 20 38 31 34 61 36 33  on ticket 814a63
d950: 66 38 2c 20 61 6c 6c 20 6f 6e 20 74 68 65 20 73  f8, all on the s
d960: 65 72 76 65 64 20 72 65 70 6f 73 69 74 6f 72 79  erved repository
d970: 3b 20 32 20 73 74 6f 70 73 20 6f 66 20 6f 6e 65  ; 2 stops of one
d980: 20 72 75 6e 20 28 6f 77 6e 65 72 2c 20 73 61 6c   run (owner, sal
d990: 6c 79 29 3b 20 33 20 66 6f 72 75 6d 20 70 6f 73  ly); 3 forum pos
d9a0: 74 73 20 61 6e 64 20 33 20 74 69 63 6b 65 74 20  ts and 3 ticket 
d9b0: 63 6f 6d 6d 65 6e 74 73 20 66 72 6f 6d 20 69 76  comments from iv
d9c0: 79 27 73 20 63 6c 6f 6e 65 3b 20 61 6e 64 20 36  y's clone; and 6
d9d0: 20 70 61 72 61 6c 6c 65 6c 20 43 47 49 20 73 74   parallel CGI st
d9e0: 61 74 75 73 20 47 45 54 73 2e 20 45 76 65 72 79  atus GETs. Every
d9f0: 20 77 72 69 74 65 72 20 61 6e 73 77 65 72 65 64   writer answered
da00: 20 6f 6b 20 77 69 74 68 20 69 74 73 20 6f 77 6e   ok with its own
da10: 20 64 69 73 74 69 6e 63 74 20 68 61 73 68 2e 20   distinct hash. 
da20: 45 61 63 68 20 61 72 74 69 66 61 63 74 20 77 61  Each artifact wa
da30: 73 20 6f 6e 20 74 68 65 20 73 65 72 76 65 72 20  s on the server 
da40: 61 6e 64 20 69 6e 64 65 78 65 64 20 28 66 6f 72  and indexed (for
da50: 75 6d 70 6f 73 74 20 6f 72 20 74 69 63 6b 65 74  umpost or ticket
da60: 63 68 6e 67 20 70 6c 75 73 20 65 76 65 6e 74 29  chng plus event)
da70: 2c 20 72 65 63 65 69 76 65 64 20 66 72 6f 6d 20  , received from 
da80: 74 68 65 20 72 69 67 68 74 20 75 73 65 72 2c 20  the right user, 
da90: 61 6e 64 20 68 65 6c 64 20 69 74 73 20 6f 77 6e  and held its own
daa0: 20 77 72 69 74 65 72 27 73 20 74 65 78 74 2e 5c   writer's text.\
dab0: 6e 28 32 29 20 50 61 72 61 6c 6c 65 6c 20 43 47  n(2) Parallel CG
dac0: 49 20 74 49 2e 73 68 2e 20 31 32 20 50 4f 53 54  I tI.sh. 12 POST
dad0: 65 64 20 63 72 65 61 74 65 73 20 28 34 20 65 61  ed creates (4 ea
dae0: 63 68 20 62 79 20 6f 77 6e 65 72 2c 20 73 61 6c  ch by owner, sal
daf0: 6c 79 20 61 6e 64 20 61 64 61 6d 2c 20 73 69 67  ly and adam, sig
db00: 6e 65 64 20 69 6e 20 74 68 72 6f 75 67 68 20 2f  ned in through /
db10: 6c 6f 67 69 6e 29 20 70 6c 75 73 20 33 20 50 4f  login) plus 3 PO
db20: 53 54 65 64 20 73 74 6f 70 73 2c 20 61 6c 6f 6e  STed stops, alon
db30: 67 73 69 64 65 20 31 30 20 73 74 61 74 75 73 20  gside 10 status 
db40: 47 45 54 73 2e 20 41 6c 6c 20 32 35 20 61 6e 73  GETs. All 25 ans
db50: 77 65 72 65 64 20 6f 6b 2e 20 45 61 63 68 20 63  wered ok. Each c
db60: 72 65 61 74 65 20 61 6e 64 20 73 74 6f 70 20 68  reate and stop h
db70: 61 64 20 61 20 64 69 73 74 69 6e 63 74 20 68 61  ad a distinct ha
db80: 73 68 20 61 6e 64 20 69 74 73 20 6f 77 6e 20 74  sh and its own t
db90: 65 78 74 20 61 6e 64 20 75 73 65 72 2c 20 69 6e  ext and user, in
dba0: 64 65 78 65 64 20 6f 6e 20 74 68 65 20 73 65 72  dexed on the ser
dbb0: 76 65 72 2e 20 54 68 65 20 47 45 54 73 20 61 6e  ver. The GETs an
dbc0: 73 77 65 72 65 64 20 61 73 20 6e 6f 62 6f 64 79  swered as nobody
dbd0: 2e 5c 6e 28 33 29 20 54 75 72 6e 20 74 61 6b 69  .\n(3) Turn taki
dbe0: 6e 67 20 28 74 48 2e 73 68 29 3a 20 61 20 73 65  ng (tH.sh): a se
dbf0: 63 6f 6e 64 20 77 72 69 74 65 72 20 6f 6e 20 74  cond writer on t
dc00: 68 65 20 73 61 6d 65 20 63 6c 6f 6e 65 20 72 75  he same clone ru
dc10: 6e 73 20 6e 6f 20 66 6f 73 73 69 6c 20 63 6f 6d  ns no fossil com
dc20: 6d 61 6e 64 20 77 68 69 6c 65 20 74 68 65 20 66  mand while the f
dc30: 69 72 73 74 20 68 6f 6c 64 73 20 74 68 65 20 74  irst holds the t
dc40: 75 72 6e 2c 20 61 6e 64 20 62 6f 74 68 20 65 6e  urn, and both en
dc50: 64 20 6f 6b 2e 5c 6e 28 34 29 20 41 6e 20 6f 75  d ok.\n(4) An ou
dc60: 74 73 69 64 65 20 77 72 69 74 65 72 20 68 6f 6c  tside writer hol
dc70: 64 69 6e 67 20 74 68 65 20 63 6c 6f 6e 65 20 66  ding the clone f
dc80: 6f 72 20 74 68 65 20 77 68 6f 6c 65 20 70 6f 73  or the whole pos
dc90: 74 20 28 74 44 2e 73 68 29 20 67 69 76 65 73 20  t (tD.sh) gives 
dca0: 6f 6b 3a 66 61 6c 73 65 20 6e 61 6d 69 6e 67 20  ok:false naming 
dcb0: 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 20 61 6e 64  clone.fossil and
dcc0: 20 27 64 61 74 61 62 61 73 65 20 69 73 20 6c 6f   'database is lo
dcd0: 63 6b 65 64 27 2e 20 4e 6f 74 68 69 6e 67 20 69  cked'. Nothing i
dce0: 73 20 77 72 69 74 74 65 6e 20 28 6d 61 78 20 72  s written (max r
dcf0: 69 64 20 75 6e 63 68 61 6e 67 65 64 29 2e 20 54  id unchanged). T
dd00: 68 65 20 6d 65 73 73 61 67 65 27 73 20 27 77 68  he message's 'wh
dd10: 61 74 20 61 6e 20 65 61 72 6c 69 65 72 20 63 6f  at an earlier co
dd20: 6d 6d 61 6e 64 20 77 72 6f 74 65 20 73 74 61 79  mmand wrote stay
dd30: 73 27 20 69 73 20 6d 69 73 6c 65 61 64 69 6e 67  s' is misleading
dd40: 20 74 68 65 72 65 2c 20 73 69 6e 63 65 20 6e 6f   there, since no
dd50: 74 68 69 6e 67 20 77 61 73 2e 5c 6e 28 35 29 20  thing was.\n(5) 
dd60: 41 6e 20 6f 75 74 73 69 64 65 20 77 72 69 74 65  An outside write
dd70: 72 20 6f 6e 20 74 68 65 20 73 65 72 76 65 64 20  r on the served 
dd80: 72 65 70 6f 73 69 74 6f 72 79 20 64 75 72 69 6e  repository durin
dd90: 67 20 61 20 43 47 49 20 63 72 65 61 74 65 20 28  g a CGI create (
dda0: 74 4a 2e 73 68 29 20 67 69 76 65 73 20 61 20 34  tJ.sh) gives a 4
ddb0: 30 33 20 6e 61 6d 69 6e 67 20 72 65 70 6f 2e 66  03 naming repo.f
ddc0: 6f 73 73 69 6c 2c 20 61 6e 64 20 6e 6f 74 68 69  ossil, and nothi
ddd0: 6e 67 20 69 73 20 77 72 69 74 74 65 6e 2e 20 73  ng is written. s
dde0: 74 61 74 75 73 20 6b 65 65 70 73 20 61 6e 73 77  tatus keeps answ
ddf0: 65 72 69 6e 67 20 32 30 30 20 6d 65 61 6e 77 68  ering 200 meanwh
de00: 69 6c 65 2e 5c 6e 28 36 29 20 41 6e 20 6f 75 74  ile.\n(6) An out
de10: 73 69 64 65 20 6c 6f 63 6b 20 6f 6e 20 74 68 65  side lock on the
de20: 20 63 68 65 63 6b 6f 75 74 20 64 61 74 61 62 61   checkout databa
de30: 73 65 20 2e 66 73 6c 63 6b 6f 75 74 20 28 74 43  se .fslckout (tC
de40: 2e 73 68 29 20 61 6e 64 20 6f 6e 20 48 4f 4d 45  .sh) and on HOME
de50: 2f 2e 66 6f 73 73 69 6c 20 28 74 4e 2e 73 68 29  /.fossil (tN.sh)
de60: 20 64 6f 65 73 20 6e 6f 74 20 61 66 66 65 63 74   does not affect
de70: 20 61 20 70 6f 73 74 20 6f 72 20 63 72 65 61 74   a post or creat
de80: 65 3b 20 62 6f 74 68 20 61 6e 73 77 65 72 65 64  e; both answered
de90: 20 6f 6b 20 77 69 74 68 20 74 68 65 69 72 20 6f   ok with their o
dea0: 77 6e 20 68 61 73 68 2e 5c 6e 28 37 29 20 54 68  wn hash.\n(7) Th
deb0: 72 65 65 20 70 61 72 61 6c 6c 65 6c 20 70 6f 6c  ree parallel pol
dec0: 6c 73 20 6f 66 20 6f 6e 65 20 6e 6f 64 65 20 28  ls of one node (
ded0: 74 4f 2e 73 68 29 20 74 61 6b 65 20 74 75 72 6e  tO.sh) take turn
dee0: 73 20 6f 6e 20 70 6f 6c 6c 2e 6c 6f 63 6b 2e 20  s on poll.lock. 
def0: 4f 6e 65 20 70 75 6c 6c 20 62 72 69 6e 67 73 20  One pull brings 
df00: 74 68 65 20 72 75 6e 2c 20 61 6e 64 20 74 68 65  the run, and the
df10: 20 72 75 6e 20 67 65 74 73 20 65 78 61 63 74 6c   run gets exactl
df20: 79 20 6f 6e 65 20 72 65 66 75 73 61 6c 20 72 65  y one refusal re
df30: 70 6f 72 74 2e 5c 6e 28 38 29 20 54 65 6d 70 6f  port.\n(8) Tempo
df40: 72 61 72 79 20 63 68 65 63 6b 6f 75 74 73 20 61  rary checkouts a
df50: 72 65 20 72 65 6d 6f 76 65 64 20 61 66 74 65 72  re removed after
df60: 20 66 61 69 6c 75 72 65 73 2c 20 61 6e 64 20 6e   failures, and n
df70: 6f 20 73 74 61 6c 65 20 63 6b 6f 75 74 3a 20 72  o stale ckout: r
df80: 6f 77 73 20 72 65 6d 61 69 6e 20 69 6e 20 74 68  ows remain in th
df90: 65 20 72 65 70 6f 73 69 74 6f 72 79 27 73 20 6f  e repository's o
dfa0: 72 20 68 6f 6d 65 27 73 20 63 6f 6e 66 69 67 2e  r home's config.
dfb0: 5c 6e 4e 6f 74 20 74 72 69 65 64 3a 20 61 20 6e  \nNot tried: a n
dfc0: 6f 64 65 20 77 69 74 68 20 61 20 72 75 6e 20 75  ode with a run u
dfd0: 73 65 72 20 69 74 20 6d 61 79 20 73 74 61 72 74  ser it may start
dfe0: 20 28 6f 6e 6c 79 20 72 65 66 75 73 61 6c 73 20   (only refusals 
dff0: 77 65 72 65 20 65 78 65 72 63 69 73 65 64 29 2c  were exercised),
e000: 20 74 68 65 20 73 65 72 76 65 72 2d 73 69 64 65   the server-side
e010: 20 68 6f 6f 6b 20 6e 6f 64 65 20 28 68 6f 6f 6b   hook node (hook
e020: 20 77 61 73 20 61 62 73 65 6e 74 29 2c 20 4d 43   was absent), MC
e030: 50 20 65 6e 74 72 79 20 70 6f 69 6e 74 73 2c 20  P entry points, 
e040: 61 6e 64 20 66 6f 72 63 69 6e 67 20 61 20 73 61  and forcing a sa
e050: 6d 65 2d 6d 69 6c 6c 69 73 65 63 6f 6e 64 20 63  me-millisecond c
e060: 6f 6c 6c 69 73 69 6f 6e 20 6f 66 20 69 64 65 6e  ollision of iden
e070: 74 69 63 61 6c 20 61 72 74 69 66 61 63 74 73 20  tical artifacts 
e080: 28 54 69 6d 65 2e 75 74 63 20 69 73 20 74 61 6b  (Time.utc is tak
e090: 65 6e 20 61 66 74 65 72 20 61 20 6c 6f 63 6b 65  en after a locke
e0a0: 64 20 72 65 61 64 2c 20 73 6f 20 69 74 20 63 6f  d read, so it co
e0b0: 75 6c 64 20 6e 6f 74 20 62 65 20 66 6f 72 63 65  uld not be force
e0c0: 64 20 77 69 74 68 6f 75 74 20 61 20 63 6c 6f 63  d without a cloc
e0d0: 6b 20 73 68 69 6d 29 2e 5c 6e 48 6f 75 73 65 6b  k shim).\nHousek
e0e0: 65 65 70 69 6e 67 3a 20 6f 6e 65 20 65 61 72 6c  eeping: one earl
e0f0: 79 20 68 6f 6c 64 2e 73 68 20 62 75 67 20 28 61  y hold.sh bug (a
e100: 20 62 75 73 79 62 6f 78 20 6d 6b 74 65 6d 70 20   busybox mktemp 
e110: 74 65 6d 70 6c 61 74 65 29 20 6d 61 64 65 20 74  template) made t
e120: 77 6f 20 66 69 66 6f 73 20 2f 69 6e 20 61 6e 64  wo fifos /in and
e130: 20 2f 6f 75 74 20 61 74 20 74 68 65 20 66 69 6c   /out at the fil
e140: 65 73 79 73 74 65 6d 20 72 6f 6f 74 2e 20 49 20  esystem root. I 
e150: 72 65 6d 6f 76 65 64 20 74 68 65 6d 20 61 74 20  removed them at 
e160: 6f 6e 63 65 2e 20 4f 74 68 65 72 20 61 67 65 6e  once. Other agen
e170: 74 73 27 20 73 65 72 76 65 72 73 20 6f 6e 20 31  ts' servers on 1
e180: 38 39 33 31 e2 80 93 31 38 39 33 33 20 61 6e 64  8931–18933 and
e190: 20 31 38 37 37 37 20 77 65 72 65 20 6c 65 66 74   18777 were left
e1a0: 20 61 6c 6f 6e 65 2e 22 0a 7d 0a 00 00 00 00 00   alone.".}......
e1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e1c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e200: 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
e210: 2f 61 74 74 61 63 6b 2d 69 6e 70 75 74 2e 6a 73  /attack-input.js
e220: 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00  on..............
e230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e260: 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
e270: 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
e280: 30 30 34 33 37 37 31 00 31 35 32 36 35 32 30 34  0043771.15265204
e290: 31 36 34 00 30 31 36 33 35 30 00 20 30 00 00 00  164.016350. 0...
e2a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e2b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e2c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e2d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e2e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e2f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e300: 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
e310: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e320: 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
e330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e340: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e350: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e370: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e380: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e3f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
e400: 7b 0a 20 22 66 69 6e 64 69 6e 67 73 22 3a 20 5b  {. "findings": [
e410: 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a  .  {.   "title":
e420: 20 22 49 6e 76 61 6c 69 64 20 55 54 46 2d 38 20   "Invalid UTF-8 
e430: 69 6e 20 61 20 72 65 71 75 65 73 74 20 66 69 65  in a request fie
e440: 6c 64 20 63 72 61 73 68 65 73 20 74 68 65 20 43  ld crashes the C
e450: 47 49 20 77 69 74 68 20 61 6e 20 75 6e 68 61 6e  GI with an unhan
e460: 64 6c 65 64 20 65 78 63 65 70 74 69 6f 6e 3b 20  dled exception; 
e470: 46 6f 73 73 69 6c 20 61 6e 73 77 65 72 73 20 32  Fossil answers 2
e480: 30 30 20 77 69 74 68 20 61 6e 20 65 6d 70 74 79  00 with an empty
e490: 20 62 6f 64 79 22 2c 0a 20 20 20 22 73 65 76 65   body",.   "seve
e4a0: 72 69 74 79 22 3a 20 22 68 69 67 68 22 2c 0a 20  rity": "high",. 
e4b0: 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22    "reproduction"
e4c0: 3a 20 22 46 72 65 73 68 20 69 6e 73 74 61 6e 63  : "Fresh instanc
e4d0: 65 3a 20 73 65 74 75 70 2e 73 68 20 2e 2e 2e 2f  e: setup.sh .../
e4e0: 61 64 76 65 72 73 61 72 79 2f 69 6e 70 75 74 20  adversary/input 
e4f0: 31 38 39 33 33 2e 20 41 6e 6f 6e 79 6d 6f 75 73  18933. Anonymous
e500: 3a 20 63 75 72 6c 20 2d 73 20 2d 6f 20 6f 20 2d  : curl -s -o o -
e510: 77 20 27 25 7b 68 74 74 70 5f 63 6f 64 65 7d 20  w '%{http_code} 
e520: 25 7b 63 6f 6e 74 65 6e 74 5f 74 79 70 65 7d 20  %{content_type} 
e530: 25 7b 73 69 7a 65 5f 64 6f 77 6e 6c 6f 61 64 7d  %{size_download}
e540: 27 20 27 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e  ' 'http://127.0.
e550: 30 2e 31 3a 31 38 39 33 33 2f 65 78 74 2f 6f 63  0.1:18933/ext/oc
e560: 78 32 2d 63 67 69 2f 72 65 63 65 69 70 74 3f 6a  x2-cgi/receipt?j
e570: 73 6f 6e 3d 6f 6e 26 61 72 74 69 66 61 63 74 73  son=on&artifacts
e580: 3d 25 66 66 27 2e 20 53 69 67 6e 65 64 20 69 6e  =%ff'. Signed in
e590: 20 61 73 20 6f 77 6e 65 72 20 28 63 6f 6f 6b 69   as owner (cooki
e5a0: 65 20 66 72 6f 6d 20 2f 6c 6f 67 69 6e 29 2c 20  e from /login), 
e5b0: 64 72 79 20 72 75 6e 73 3a 20 63 72 65 61 74 65  dry runs: create
e5c0: 3f 6a 73 6f 6e 3d 6f 6e 26 64 72 79 5f 72 75 6e  ?json=on&dry_run
e5d0: 3d 74 72 75 65 26 6f 62 6a 65 63 74 69 76 65 3d  =true&objective=
e5e0: 78 26 6e 6f 64 65 3d 25 66 66 20 3b 20 73 65 63  x&node=%ff ; sec
e5f0: 72 65 74 3f 6a 73 6f 6e 3d 6f 6e 26 64 72 79 5f  ret?json=on&dry_
e600: 72 75 6e 3d 74 72 75 65 26 6e 61 6d 65 3d 25 66  run=true&name=%f
e610: 66 26 76 61 6c 75 65 3d 79 20 3b 20 61 70 70 72  f&value=y ; appr
e620: 6f 76 65 3f 6a 73 6f 6e 3d 6f 6e 26 64 72 79 5f  ove?json=on&dry_
e630: 72 75 6e 3d 74 72 75 65 26 6c 6f 67 69 6e 3d 7a  run=true&login=z
e640: 65 64 26 6b 65 79 3d 61 62 63 26 63 61 70 61 62  ed&key=abc&capab
e650: 69 6c 69 74 69 65 73 3d 25 66 66 2e 20 52 75 6e  ilities=%ff. Run
e660: 20 62 79 20 68 61 6e 64 20 74 6f 20 73 65 65 20   by hand to see 
e670: 73 74 64 65 72 72 3a 20 65 6e 76 20 2d 69 20 46  stderr: env -i F
e680: 4f 53 53 49 4c 5f 52 45 50 4f 53 49 54 4f 52 59  OSSIL_REPOSITORY
e690: 3d 24 44 49 52 2f 73 65 72 76 65 72 2f 72 65 70  =$DIR/server/rep
e6a0: 6f 2e 66 6f 73 73 69 6c 20 46 4f 53 53 49 4c 5f  o.fossil FOSSIL_
e6b0: 55 53 45 52 3d 6e 6f 62 6f 64 79 20 46 4f 53 53  USER=nobody FOSS
e6c0: 49 4c 5f 43 41 50 41 42 49 4c 49 54 49 45 53 3d  IL_CAPABILITIES=
e6d0: 67 6a 6f 72 7a 20 52 45 51 55 45 53 54 5f 4d 45  gjorz REQUEST_ME
e6e0: 54 48 4f 44 3d 47 45 54 20 51 55 45 52 59 5f 53  THOD=GET QUERY_S
e6f0: 54 52 49 4e 47 3d 27 6a 73 6f 6e 3d 6f 6e 26 61  TRING='json=on&a
e700: 72 74 69 66 61 63 74 73 3d 25 66 66 25 66 65 27  rtifacts=%ff%fe'
e710: 20 50 41 54 48 5f 49 4e 46 4f 3d 2f 65 78 74 2f   PATH_INFO=/ext/
e720: 6f 63 78 32 2d 63 67 69 2f 72 65 63 65 69 70 74  ocx2-cgi/receipt
e730: 20 24 44 49 52 2f 65 78 74 2f 6f 63 78 32 2d 63   $DIR/ext/ocx2-c
e740: 67 69 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65  gi",.   "observe
e750: 64 22 3a 20 22 41 6c 6c 20 66 6f 75 72 20 61 6e  d": "All four an
e760: 73 77 65 72 20 27 32 30 30 20 61 70 70 6c 69 63  swer '200 applic
e770: 61 74 69 6f 6e 2f 78 2d 66 6f 73 73 69 6c 2d 61  ation/x-fossil-a
e780: 72 74 69 66 61 63 74 20 30 27 3a 20 6e 6f 20 4a  rtifact 0': no J
e790: 53 4f 4e 20 61 6e 64 20 6e 6f 20 72 65 61 73 6f  SON and no reaso
e7a0: 6e 2e 20 57 69 74 68 20 74 68 65 20 70 61 67 65  n. With the page
e7b0: 20 66 6f 72 6d 20 28 6e 6f 20 6a 73 6f 6e 3d 6f   form (no json=o
e7c0: 6e 29 20 74 68 65 20 72 65 73 75 6c 74 20 69 73  n) the result is
e7d0: 20 74 68 65 20 73 61 6d 65 2e 20 54 68 65 20 70   the same. The p
e7e0: 72 6f 63 65 73 73 20 65 78 69 74 73 20 31 20 77  rocess exits 1 w
e7f0: 69 74 68 20 27 55 6e 68 61 6e 64 6c 65 64 20 65  ith 'Unhandled e
e800: 78 63 65 70 74 69 6f 6e 3a 20 52 65 67 65 78 20  xception: Regex 
e810: 6d 61 74 63 68 20 65 72 72 6f 72 3a 20 55 54 46  match error: UTF
e820: 2d 38 20 65 72 72 6f 72 3a 20 69 6c 6c 65 67 61  -8 error: illega
e830: 6c 20 62 79 74 65 20 28 30 78 66 65 20 6f 72 20  l byte (0xfe or 
e840: 30 78 66 66 29 20 28 41 72 67 75 6d 65 6e 74 45  0xff) (ArgumentE
e850: 72 72 6f 72 29 27 20 61 6e 64 20 61 20 66 75 6c  rror)' and a ful
e860: 6c 20 62 61 63 6b 74 72 61 63 65 2c 20 77 68 69  l backtrace, whi
e870: 63 68 20 67 6f 65 73 20 74 6f 20 73 65 72 76 65  ch goes to serve
e880: 72 2e 6c 6f 67 2e 20 54 68 65 20 63 72 61 73 68  r.log. The crash
e890: 20 73 69 74 65 73 3a 20 4f 43 58 3a 3a 52 65 63   sites: OCX::Rec
e8a0: 65 69 70 74 43 6f 6d 6d 61 6e 64 3a 3a 72 75 6e  eiptCommand::run
e8b0: 20 28 41 52 54 49 46 41 43 54 20 6d 61 74 63 68   (ARTIFACT match
e8c0: 29 2c 20 4f 43 58 3a 3a 4d 65 73 73 61 67 65 73  ), OCX::Messages
e8d0: 3a 3a 62 6c 6f 63 6b 73 20 76 69 61 20 43 72 65  ::blocks via Cre
e8e0: 61 74 65 43 6f 6d 6d 61 6e 64 2e 77 72 69 74 74  ateCommand.writt
e8f0: 65 6e 2c 20 53 65 63 72 65 74 43 6f 6d 6d 61 6e  en, SecretComman
e900: 64 2e 72 75 6e 20 28 53 45 43 52 45 54 5f 4e 41  d.run (SECRET_NA
e910: 4d 45 29 2c 20 61 6e 64 20 43 61 70 61 62 69 6c  ME), and Capabil
e920: 69 74 69 65 73 2e 70 61 72 73 65 20 69 6e 73 69  ities.parse insi
e930: 64 65 20 49 6e 70 75 74 2e 66 72 6f 6d 5f 73 74  de Input.from_st
e940: 72 69 6e 67 73 20 66 6f 72 20 61 70 70 72 6f 76  rings for approv
e950: 65 2e 22 2c 0a 20 20 20 22 65 78 70 65 63 74 65  e.",.   "expecte
e960: 64 22 3a 20 22 54 68 65 20 74 61 73 6b 27 73 20  d": "The task's 
e970: 72 75 6c 65 3a 20 65 76 65 72 79 20 72 65 66 75  rule: every refu
e980: 73 61 6c 20 73 61 79 73 20 77 68 79 2c 20 61 6e  sal says why, an
e990: 64 20 6e 6f 74 68 69 6e 67 20 63 72 61 73 68 65  d nothing crashe
e9a0: 73 20 77 69 74 68 20 61 20 62 61 63 6b 74 72 61  s with a backtra
e9b0: 63 65 20 6f 72 20 61 6e 73 77 65 72 73 20 35 30  ce or answers 50
e9c0: 30 2e 20 73 72 63 2f 6f 63 78 2f 72 65 66 75 73  0. src/ocx/refus
e9d0: 61 6c 2e 63 72 20 73 61 79 73 20 65 76 65 72 79  al.cr says every
e9e0: 20 4f 43 58 20 65 78 63 65 70 74 69 6f 6e 20 64   OCX exception d
e9f0: 65 72 69 76 65 73 20 66 72 6f 6d 20 52 65 66 75  erives from Refu
ea00: 73 61 6c 20 27 73 6f 20 61 20 74 6f 6f 6c 27 73  sal 'so a tool's
ea10: 20 61 6e 73 77 65 72 20 72 65 73 63 75 65 73 20   answer rescues 
ea20: 74 68 69 73 20 6f 6e 65 20 63 6c 61 73 73 20 61  this one class a
ea30: 6e 64 20 61 6e 73 77 65 72 73 20 61 20 72 65 66  nd answers a ref
ea40: 75 73 61 6c 2c 20 69 6e 20 65 76 65 72 79 20 65  usal, in every e
ea50: 6e 74 72 79 20 70 6f 69 6e 74 2c 20 6e 65 76 65  ntry point, neve
ea60: 72 20 61 20 63 72 61 73 68 27 2e 20 41 20 66 69  r a crash'. A fi
ea70: 65 6c 64 20 74 68 61 74 20 69 73 20 6e 6f 74 20  eld that is not 
ea80: 55 54 46 2d 38 20 73 68 6f 75 6c 64 20 67 65 74  UTF-8 should get
ea90: 20 61 20 55 73 61 67 65 20 72 65 66 75 73 61 6c   a Usage refusal
eaa0: 2c 20 34 30 33 20 77 69 74 68 20 4a 53 4f 4e 2e  , 403 with JSON.
eab0: 22 2c 0a 20 20 20 22 63 6f 64 65 22 3a 20 22 73  ",.   "code": "s
eac0: 72 63 2f 6f 63 78 2f 63 67 69 2e 63 72 20 43 67  rc/ocx/cgi.cr Cg
ead0: 69 2e 66 6f 72 6d 20 70 61 73 73 65 73 20 55 52  i.form passes UR
eae0: 49 3a 3a 50 61 72 61 6d 73 20 76 61 6c 75 65 73  I::Params values
eaf0: 20 74 68 72 6f 75 67 68 20 77 69 74 68 6f 75 74   through without
eb00: 20 63 68 65 63 6b 69 6e 67 20 53 74 72 69 6e 67   checking String
eb10: 23 76 61 6c 69 64 5f 65 6e 63 6f 64 69 6e 67 3f  #valid_encoding?
eb20: 2c 20 61 6e 64 20 43 67 69 2e 61 6e 73 77 65 72  , and Cgi.answer
eb30: 20 72 65 73 63 75 65 73 20 6f 6e 6c 79 20 55 73   rescues only Us
eb40: 61 67 65 2e 20 73 72 63 2f 6f 63 78 2f 63 6f 6d  age. src/ocx/com
eb50: 6d 61 6e 64 2e 63 72 20 43 6f 6d 6d 61 6e 64 2e  mand.cr Command.
eb60: 61 6e 73 77 65 72 20 72 65 73 63 75 65 73 20 6f  answer rescues o
eb70: 6e 6c 79 20 3a 3a 4f 43 58 3a 3a 52 65 66 75 73  nly ::OCX::Refus
eb80: 61 6c 20 61 72 6f 75 6e 64 20 72 75 6e 28 29 2e  al around run().
eb90: 20 52 65 67 65 78 20 63 68 65 63 6b 73 20 6f 6e   Regex checks on
eba0: 20 72 61 77 20 69 6e 70 75 74 3a 20 73 72 63 2f   raw input: src/
ebb0: 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f 72 65 63  ocx/commands/rec
ebc0: 65 69 70 74 2e 63 72 3a 31 35 33 20 28 61 2e 6d  eipt.cr:153 (a.m
ebd0: 61 74 63 68 65 73 3f 28 41 52 54 49 46 41 43 54  atches?(ARTIFACT
ebe0: 29 29 2c 20 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d  )), src/ocx/comm
ebf0: 61 6e 64 73 2f 73 65 63 72 65 74 2e 63 72 3a 35  ands/secret.cr:5
ec00: 39 2c 20 73 72 63 2f 6f 63 78 2f 65 6c 65 6d 65  9, src/ocx/eleme
ec10: 6e 74 73 2e 63 72 3a 32 35 34 20 28 43 61 70 61  nts.cr:254 (Capa
ec20: 62 69 6c 69 74 69 65 73 2e 70 61 72 73 65 29 2c  bilities.parse),
ec30: 20 73 72 63 2f 6f 63 78 2f 6d 65 73 73 61 67 65   src/ocx/message
ec40: 73 2e 63 72 3a 33 31 20 28 62 6c 6f 63 6b 73 2c  s.cr:31 (blocks,
ec50: 20 6c 69 6e 65 2e 6d 61 74 63 68 29 2e 20 4c 6f   line.match). Lo
ec60: 67 23 70 65 72 66 6f 72 6d 20 28 73 72 63 2f 6f  g#perform (src/o
ec70: 63 78 2f 6c 6f 67 2e 63 72 3a 38 32 29 20 72 65  cx/log.cr:82) re
ec80: 73 63 75 65 73 20 61 6e 79 20 65 72 72 6f 72 20  scues any error 
ec90: 6f 6e 6c 79 20 66 6f 72 20 63 68 65 63 6b 73 20  only for checks 
eca0: 72 75 6e 20 74 68 72 6f 75 67 68 20 6c 6f 67 2e  run through log.
ecb0: 63 68 65 63 6b 2c 20 73 6f 20 74 68 65 20 73 61  check, so the sa
ecc0: 6d 65 20 62 79 74 65 73 20 69 6e 73 69 64 65 20  me bytes inside 
ecd0: 61 20 63 68 65 63 6b 20 62 65 63 6f 6d 65 20 61  a check become a
ece0: 20 72 65 66 75 73 61 6c 3a 20 74 68 72 65 61 64   refusal: thread
ecf0: 2c 20 70 6f 73 74 20 2d 2d 74 6f 20 61 6e 64 20  , post --to and 
ed00: 61 75 64 69 74 20 2d 2d 63 68 65 63 6b 69 6e 20  audit --checkin 
ed10: 61 6e 73 77 65 72 20 27 66 69 6e 64 5f 77 68 65  answer 'find_whe
ed20: 72 65 20 66 61 69 6c 65 64 3a 20 52 65 67 65 78  re failed: Regex
ed30: 20 6d 61 74 63 68 20 65 72 72 6f 72 20 2e 2e 2e   match error ...
ed40: 27 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20  '.".  },.  {.   
ed50: 22 74 69 74 6c 65 22 3a 20 22 4f 76 65 72 20 4d  "title": "Over M
ed60: 43 50 2c 20 6f 6e 65 20 62 61 64 20 61 72 67 75  CP, one bad argu
ed70: 6d 65 6e 74 20 63 72 61 73 68 65 73 20 74 68 65  ment crashes the
ed80: 20 73 74 64 69 6f 20 73 65 72 76 65 72 3b 20 6f   stdio server; o
ed90: 76 65 72 20 48 54 54 50 20 69 74 20 61 6e 73 77  ver HTTP it answ
eda0: 65 72 73 20 35 30 30 22 2c 0a 20 20 20 22 73 65  ers 500",.   "se
edb0: 76 65 72 69 74 79 22 3a 20 22 68 69 67 68 22 2c  verity": "high",
edc0: 0a 20 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f  .   "reproductio
edd0: 6e 22 3a 20 22 49 6e 20 69 76 79 27 73 20 63 6c  n": "In ivy's cl
ede0: 6f 6e 65 20 63 68 65 63 6b 6f 75 74 20 28 24 44  one checkout ($D
edf0: 49 52 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74 72  IR/clones/ivy/tr
ee00: 65 65 29 2c 20 73 74 64 69 6f 3a 20 73 65 6e 64  ee), stdio: send
ee10: 20 74 77 6f 20 6c 69 6e 65 73 20 74 6f 20 60 6f   two lines to `o
ee20: 63 78 32 20 2d 2d 6d 63 70 60 2e 20 4c 69 6e 65  cx2 --mcp`. Line
ee30: 20 31 3a 20 7b 5c 22 6a 73 6f 6e 72 70 63 5c 22   1: {\"jsonrpc\"
ee40: 3a 5c 22 32 2e 30 5c 22 2c 5c 22 69 64 5c 22 3a  :\"2.0\",\"id\":
ee50: 31 2c 5c 22 6d 65 74 68 6f 64 5c 22 3a 5c 22 74  1,\"method\":\"t
ee60: 6f 6f 6c 73 2f 63 61 6c 6c 5c 22 2c 5c 22 70 61  ools/call\",\"pa
ee70: 72 61 6d 73 5c 22 3a 7b 5c 22 6e 61 6d 65 5c 22  rams\":{\"name\"
ee80: 3a 5c 22 6f 63 78 5f 65 64 69 74 5c 22 2c 5c 22  :\"ocx_edit\",\"
ee90: 61 72 67 75 6d 65 6e 74 73 5c 22 3a 7b 5c 22 70  arguments\":{\"p
eea0: 61 74 68 5c 22 3a 5c 22 52 45 41 44 4d 45 2e 6d  ath\":\"README.m
eeb0: 64 5c 22 2c 5c 22 6f 6c 64 5c 22 3a 5c 22 3c 72  d\",\"old\":\"<r
eec0: 61 77 20 62 79 74 65 20 30 78 46 46 3e 5c 22 2c  aw byte 0xFF>\",
eed0: 5c 22 6e 65 77 5c 22 3a 5c 22 78 5c 22 2c 5c 22  \"new\":\"x\",\"
eee0: 64 72 79 5f 72 75 6e 5c 22 3a 74 72 75 65 7d 7d  dry_run\":true}}
eef0: 7d 2e 20 4c 69 6e 65 20 32 20 69 73 20 61 6e 20  }. Line 2 is an 
ef00: 6f 63 78 5f 65 63 68 6f 20 63 61 6c 6c 2e 20 48  ocx_echo call. H
ef10: 54 54 50 3a 20 73 74 61 72 74 20 60 6f 63 78 32  TTP: start `ocx2
ef20: 20 2d 2d 6d 63 70 2d 68 74 74 70 20 31 32 37 2e   --mcp-http 127.
ef30: 30 2e 30 2e 31 3a 31 38 39 34 31 60 20 69 6e 20  0.0.1:18941` in 
ef40: 74 68 65 20 73 61 6d 65 20 63 68 65 63 6b 6f 75  the same checkou
ef50: 74 2c 20 74 68 65 6e 20 50 4f 53 54 20 2f 6d 63  t, then POST /mc
ef60: 70 20 77 69 74 68 20 74 68 65 20 73 61 6d 65 20  p with the same 
ef70: 6d 65 73 73 61 67 65 2c 20 6f 72 20 77 69 74 68  message, or with
ef80: 20 61 20 72 61 77 20 30 78 46 46 20 69 6e 20 6f   a raw 0xFF in o
ef90: 63 78 5f 73 61 76 65 20 74 69 74 6c 65 2f 69 6e  cx_save title/in
efa0: 74 65 6e 74 2f 65 78 70 72 65 73 73 69 6f 6e 2f  tent/expression/
efb0: 64 65 6d 6f 6e 73 74 72 61 74 65 73 2c 20 6f 63  demonstrates, oc
efc0: 78 5f 77 69 6b 69 5f 65 64 69 74 20 6f 6c 64 20  x_wiki_edit old 
efd0: 6f 72 20 6f 63 78 5f 70 6f 73 74 20 74 65 78 74  or ocx_post text
efe0: 2e 20 46 75 72 74 68 65 72 20 35 30 30 73 3a 20  . Further 500s: 
eff0: 6f 63 78 5f 65 64 69 74 20 6f 6c 64 20 6f 72 20  ocx_edit old or 
f000: 6f 63 78 5f 77 69 6b 69 5f 65 64 69 74 20 6f 6c  ocx_wiki_edit ol
f010: 64 20 73 65 74 20 74 6f 20 27 78 27 2a 32 30 30  d set to 'x'*200
f020: 30 30 30 2c 20 61 6e 64 20 6f 63 78 5f 73 74 61  000, and ocx_sta
f030: 67 65 20 63 68 65 63 6b 6f 75 74 20 6f 72 20 6f  ge checkout or o
f040: 63 78 5f 61 63 63 65 70 74 2f 6f 63 78 5f 72 6f  cx_accept/ocx_ro
f050: 6c 6c 62 61 63 6b 20 72 6f 6f 74 20 63 6f 6e 74  llback root cont
f060: 61 69 6e 69 6e 67 20 5c 5c 75 30 30 30 30 2e 22  aining \\u0000."
f070: 2c 0a 20 20 20 22 6f 62 73 65 72 76 65 64 22 3a  ,.   "observed":
f080: 20 22 73 74 64 69 6f 3a 20 65 78 69 74 20 31 2c   "stdio: exit 1,
f090: 20 27 55 6e 68 61 6e 64 6c 65 64 20 65 78 63 65   'Unhandled exce
f0a0: 70 74 69 6f 6e 3a 20 55 54 46 2d 38 20 65 72 72  ption: UTF-8 err
f0b0: 6f 72 3a 20 69 6c 6c 65 67 61 6c 20 62 79 74 65  or: illegal byte
f0c0: 20 28 30 78 66 65 20 6f 72 20 30 78 66 66 29 20   (0xfe or 0xff) 
f0d0: 61 74 20 30 20 28 41 72 67 75 6d 65 6e 74 45 72  at 0 (ArgumentEr
f0e0: 72 6f 72 29 27 20 66 72 6f 6d 20 4f 43 58 3a 3a  ror)' from OCX::
f0f0: 45 64 69 74 43 6f 6d 6d 61 6e 64 3a 3a 63 68 61  EditCommand::cha
f100: 6e 67 65 64 2c 20 61 6e 64 20 74 68 65 20 73 65  nged, and the se
f110: 63 6f 6e 64 20 72 65 71 75 65 73 74 20 67 65 74  cond request get
f120: 73 20 6e 6f 20 61 6e 73 77 65 72 2e 20 54 68 65  s no answer. The
f130: 20 61 67 65 6e 74 27 73 20 4d 43 50 20 73 65 73   agent's MCP ses
f140: 73 69 6f 6e 20 69 73 20 67 6f 6e 65 2e 20 48 54  sion is gone. HT
f150: 54 50 3a 20 27 35 30 30 20 49 6e 74 65 72 6e 61  TP: '500 Interna
f160: 6c 20 53 65 72 76 65 72 20 45 72 72 6f 72 27 2e  l Server Error'.
f170: 20 53 65 72 76 65 72 20 6c 6f 67 20 72 65 61 73   Server log reas
f180: 6f 6e 73 3a 20 27 52 65 67 65 78 20 6d 61 74 63  ons: 'Regex matc
f190: 68 20 65 72 72 6f 72 3a 20 55 54 46 2d 38 20 65  h error: UTF-8 e
f1a0: 72 72 6f 72 27 2c 20 27 53 74 72 69 6e 67 20 63  rror', 'String c
f1b0: 6f 6e 74 61 69 6e 73 20 6e 75 6c 6c 20 62 79 74  ontains null byt
f1c0: 65 20 28 41 72 67 75 6d 65 6e 74 45 72 72 6f 72  e (ArgumentError
f1d0: 29 27 2c 20 27 72 65 67 75 6c 61 72 20 65 78 70  )', 'regular exp
f1e0: 72 65 73 73 69 6f 6e 20 69 73 20 74 6f 6f 20 6c  ression is too l
f1f0: 61 72 67 65 20 61 74 20 30 20 28 41 72 67 75 6d  arge at 0 (Argum
f200: 65 6e 74 45 72 72 6f 72 29 27 2e 20 52 65 70 6c  entError)'. Repl
f210: 69 65 73 20 74 68 61 74 20 64 6f 20 63 6f 6d 65  ies that do come
f220: 20 62 61 63 6b 20 63 61 6e 20 63 61 72 72 79 20   back can carry 
f230: 72 61 77 20 30 78 46 46 20 62 79 74 65 73 2c 20  raw 0xFF bytes, 
f240: 77 68 69 63 68 20 69 73 20 6e 6f 74 20 76 61 6c  which is not val
f250: 69 64 20 55 54 46 2d 38 20 4a 53 4f 4e 2e 22 2c  id UTF-8 JSON.",
f260: 0a 20 20 20 22 65 78 70 65 63 74 65 64 22 3a 20  .   "expected": 
f270: 22 73 72 63 2f 6f 63 78 2f 6d 63 70 2e 63 72 3a  "src/ocx/mcp.cr:
f280: 20 27 41 20 6d 65 73 73 61 67 65 20 6f 66 20 74   'A message of t
f290: 68 65 20 77 72 6f 6e 67 20 73 68 61 70 65 20 69  he wrong shape i
f2a0: 73 20 61 6e 73 77 65 72 65 64 20 77 69 74 68 20  s answered with 
f2b0: 61 20 4a 53 4f 4e 2d 52 50 43 20 65 72 72 6f 72  a JSON-RPC error
f2c0: 20 61 6e 64 20 74 68 65 20 73 65 72 76 65 72 20   and the server 
f2d0: 6b 65 65 70 73 20 73 65 72 76 69 6e 67 2e 27 20  keeps serving.' 
f2e0: 41 72 67 75 6d 65 6e 74 73 20 74 68 61 74 20 64  Arguments that d
f2f0: 6f 20 6e 6f 74 20 72 65 61 64 20 61 72 65 20 27  o not read are '
f300: 61 20 72 65 66 75 73 61 6c 2c 20 6c 69 6b 65 20  a refusal, like 
f310: 61 6e 79 20 6f 74 68 65 72 27 2e 20 4e 6f 20 35  any other'. No 5
f320: 30 30 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22 3a  00.",.   "code":
f330: 20 22 73 72 63 2f 6f 63 78 2f 6d 63 70 2e 63 72   "src/ocx/mcp.cr
f340: 20 4d 63 70 2e 61 6e 73 77 65 72 20 72 65 73 63   Mcp.answer resc
f350: 75 65 73 20 6f 6e 6c 79 20 55 73 61 67 65 2e 20  ues only Usage. 
f360: 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73  src/ocx/commands
f370: 2f 65 64 69 74 69 6e 67 2e 63 72 3a 39 35 20 60  /editing.cr:95 `
f380: 74 65 78 74 2e 73 63 61 6e 28 52 65 67 65 78 2e  text.scan(Regex.
f390: 6e 65 77 28 52 65 67 65 78 2e 65 73 63 61 70 65  new(Regex.escape
f3a0: 28 69 6e 70 75 74 2e 6f 6c 64 29 29 29 60 20 63  (input.old)))` c
f3b0: 6f 6d 70 69 6c 65 73 20 75 73 65 72 20 74 65 78  ompiles user tex
f3c0: 74 20 61 73 20 61 20 72 65 67 65 78 2c 20 77 68  t as a regex, wh
f3d0: 69 63 68 20 66 61 69 6c 73 20 6f 6e 20 69 6e 76  ich fails on inv
f3e0: 61 6c 69 64 20 55 54 46 2d 38 20 61 6e 64 20 6f  alid UTF-8 and o
f3f0: 6e 20 76 65 72 79 20 6c 6f 6e 67 20 74 65 78 74  n very long text
f400: 3b 20 61 20 70 6c 61 69 6e 20 73 75 62 73 74 72  ; a plain substr
f410: 69 6e 67 20 63 6f 75 6e 74 20 77 6f 75 6c 64 20  ing count would 
f420: 61 76 6f 69 64 20 62 6f 74 68 2e 20 73 72 63 2f  avoid both. src/
f430: 6f 63 78 2f 6d 63 70 5f 68 74 74 70 2e 63 72 20  ocx/mcp_http.cr 
f440: 61 6e 73 77 65 72 28 29 20 68 61 73 20 6e 6f 20  answer() has no 
f450: 72 65 73 63 75 65 2c 20 73 6f 20 43 72 79 73 74  rescue, so Cryst
f460: 61 6c 27 73 20 48 54 54 50 3a 3a 53 65 72 76 65  al's HTTP::Serve
f470: 72 20 74 75 72 6e 73 20 74 68 65 20 65 72 72 6f  r turns the erro
f480: 72 20 69 6e 74 6f 20 61 20 35 30 30 2e 20 4a 53  r into a 500. JS
f490: 4f 4e 2e 70 61 72 73 65 20 61 63 63 65 70 74 73  ON.parse accepts
f4a0: 20 72 61 77 20 69 6e 76 61 6c 69 64 20 62 79 74   raw invalid byt
f4b0: 65 73 20 69 6e 73 69 64 65 20 73 74 72 69 6e 67  es inside string
f4c0: 73 2c 20 73 6f 20 6e 6f 74 68 69 6e 67 20 63 68  s, so nothing ch
f4d0: 65 63 6b 73 20 74 68 65 20 65 6e 63 6f 64 69 6e  ecks the encodin
f4e0: 67 20 61 74 20 74 68 65 20 65 64 67 65 2e 22 0a  g at the edge.".
f4f0: 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74    },.  {.   "tit
f500: 6c 65 22 3a 20 22 52 65 66 75 73 61 6c 73 20 73  le": "Refusals s
f510: 65 6e 74 20 74 6f 20 61 6e 6f 6e 79 6d 6f 75 73  ent to anonymous
f520: 20 77 65 62 20 75 73 65 72 73 20 63 6f 6e 74 61   web users conta
f530: 69 6e 20 61 20 66 75 6c 6c 20 43 72 79 73 74 61  in a full Crysta
f540: 6c 20 62 61 63 6b 74 72 61 63 65 20 77 69 74 68  l backtrace with
f550: 20 74 68 65 20 70 72 6f 67 72 61 6d 27 73 20 61   the program's a
f560: 62 73 6f 6c 75 74 65 20 70 61 74 68 73 22 2c 0a  bsolute paths",.
f570: 20 20 20 22 73 65 76 65 72 69 74 79 22 3a 20 22     "severity": "
f580: 6d 65 64 69 75 6d 22 2c 0a 20 20 20 22 72 65 70  medium",.   "rep
f590: 72 6f 64 75 63 74 69 6f 6e 22 3a 20 22 63 75 72  roduction": "cur
f5a0: 6c 20 2d 73 20 27 68 74 74 70 3a 2f 2f 31 32 37  l -s 'http://127
f5b0: 2e 30 2e 30 2e 31 3a 31 38 39 33 33 2f 65 78 74  .0.0.1:18933/ext
f5c0: 2f 6f 63 78 32 2d 63 67 69 2f 72 65 63 65 69 70  /ocx2-cgi/receip
f5d0: 74 3f 6a 73 6f 6e 3d 6f 6e 26 63 61 70 61 62 69  t?json=on&capabi
f5e0: 6c 69 74 69 65 73 5f 6f 66 3d 61 25 30 30 62 27  lities_of=a%00b'
f5f0: 20 28 61 73 20 6e 6f 62 6f 64 79 29 2e 20 41 6c   (as nobody). Al
f600: 73 6f 20 75 6e 61 75 64 69 74 65 64 3f 6a 73 6f  so unaudited?jso
f610: 6e 3d 6f 6e 26 62 72 61 6e 63 68 3d 25 30 30 2c  n=on&branch=%00,
f620: 20 61 6e 64 20 63 72 65 61 74 65 3f 6a 73 6f 6e   and create?json
f630: 3d 6f 6e 26 64 72 79 5f 72 75 6e 3d 74 72 75 65  =on&dry_run=true
f640: 26 6f 62 6a 65 63 74 69 76 65 3d 78 26 70 61 74  &objective=x&pat
f650: 74 65 72 6e 3d 25 31 62 25 30 30 20 61 73 20 6f  tern=%1b%00 as o
f660: 77 6e 65 72 2e 22 2c 0a 20 20 20 22 6f 62 73 65  wner.",.   "obse
f670: 72 76 65 64 22 3a 20 22 48 54 54 50 20 34 30 33  rved": "HTTP 403
f680: 2e 20 73 74 6f 70 70 65 64 20 69 73 20 33 33 20  . stopped is 33 
f690: 6c 69 6e 65 73 3a 20 5c 22 72 65 61 64 5f 63 61  lines: \"read_ca
f6a0: 70 61 62 69 6c 69 74 69 65 73 20 66 61 69 6c 65  pabilities faile
f6b0: 64 3a 20 45 72 72 6f 72 20 65 78 65 63 75 74 69  d: Error executi
f6c0: 6e 67 20 70 72 6f 63 65 73 73 3a 20 27 66 6f 73  ng process: 'fos
f6d0: 73 69 6c 27 3a 20 53 74 72 69 6e 67 20 63 6f 6e  sil': String con
f6e0: 74 61 69 6e 73 20 6e 75 6c 6c 20 62 79 74 65 20  tains null byte 
f6f0: 28 41 72 67 75 6d 65 6e 74 45 72 72 6f 72 29 5c  (ArgumentError)\
f700: 5c 6e 20 20 66 72 6f 6d 20 2f 74 6d 70 2f 2e 2e  \n  from /tmp/..
f710: 2e 2f 69 6e 70 75 74 2f 65 78 74 2f 6f 63 78 32  ./input/ext/ocx2
f720: 2d 63 67 69 20 69 6e 20 27 45 78 63 65 70 74 69  -cgi in 'Excepti
f730: 6f 6e 3a 3a 43 61 6c 6c 53 74 61 63 6b 3a 3a 75  on::CallStack::u
f740: 6e 77 69 6e 64 2e 2e 2e 27 20 2e 2e 2e 20 69 6e  nwind...' ... in
f750: 20 27 53 74 72 69 6e 67 23 63 68 65 63 6b 5f 6e   'String#check_n
f760: 6f 5f 6e 75 6c 6c 5f 62 79 74 65 3c 4e 69 6c 3e  o_null_byte<Nil>
f770: 3a 53 74 72 69 6e 67 27 5c 22 2e 20 54 68 65 20  :String'\". The 
f780: 73 61 6d 65 20 74 65 78 74 20 61 70 70 65 61 72  same text appear
f790: 73 20 6f 6e 20 74 68 65 20 70 61 67 65 20 61 6e  s on the page an
f7a0: 64 20 69 6e 20 4d 43 50 20 61 6e 73 77 65 72 73  d in MCP answers
f7b0: 20 28 65 2e 67 2e 20 6f 63 78 5f 61 75 64 69 74   (e.g. ocx_audit
f7c0: 20 63 68 65 63 6b 69 6e 20 77 69 74 68 20 4e 55   checkin with NU
f7d0: 4c 29 2e 22 2c 0a 20 20 20 22 65 78 70 65 63 74  L).",.   "expect
f7e0: 65 64 22 3a 20 22 41 20 6f 6e 65 2d 6c 69 6e 65  ed": "A one-line
f7f0: 20 72 65 61 73 6f 6e 2c 20 73 75 63 68 20 61 73   reason, such as
f800: 20 27 63 61 70 61 62 69 6c 69 74 69 65 73 5f 6f   'capabilities_o
f810: 66 20 68 6f 6c 64 73 20 61 20 4e 55 4c 20 62 79  f holds a NUL by
f820: 74 65 27 2c 20 77 69 74 68 20 6e 6f 20 62 61 63  te', with no bac
f830: 6b 74 72 61 63 65 2e 20 41 6e 79 6f 6e 65 20 6d  ktrace. Anyone m
f840: 61 79 20 72 75 6e 20 72 65 63 65 69 70 74 2c 20  ay run receipt, 
f850: 73 6f 20 74 68 65 20 69 6e 74 65 72 6e 61 6c 73  so the internals
f860: 20 72 65 61 63 68 20 61 6e 6f 6e 79 6d 6f 75 73   reach anonymous
f870: 20 76 69 65 77 65 72 73 2e 22 2c 0a 20 20 20 22   viewers.",.   "
f880: 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f  code": "src/ocx/
f890: 6c 6f 67 2e 63 72 3a 38 32 20 4c 6f 67 23 70 65  log.cr:82 Log#pe
f8a0: 72 66 6f 72 6d 20 62 75 69 6c 64 73 20 52 65 66  rform builds Ref
f8b0: 75 73 65 64 2e 6e 65 77 28 5c 22 23 7b 6f 70 2e  used.new(\"#{op.
f8c0: 6f 70 7d 20 66 61 69 6c 65 64 3a 20 23 7b 65 2e  op} failed: #{e.
f8d0: 6d 65 73 73 61 67 65 20 2e 2e 2e 7d 5c 22 29 2e  message ...}\").
f8e0: 20 54 68 65 20 6d 65 73 73 61 67 65 20 6f 66 20   The message of 
f8f0: 43 72 79 73 74 61 6c 27 73 20 50 72 6f 63 65 73  Crystal's Proces
f900: 73 20 73 70 61 77 6e 20 65 72 72 6f 72 20 65 6d  s spawn error em
f910: 62 65 64 73 20 74 68 65 20 69 6e 6e 65 72 20 65  beds the inner e
f920: 78 63 65 70 74 69 6f 6e 27 73 20 62 61 63 6b 74  xception's backt
f930: 72 61 63 65 2e 20 46 6f 73 73 69 6c 3a 3a 50 6c  race. Fossil::Pl
f940: 61 63 65 23 68 6f 73 74 65 64 20 28 73 72 63 2f  ace#hosted (src/
f950: 6f 63 78 2f 66 6f 73 73 69 6c 2e 63 72 29 20 70  ocx/fossil.cr) p
f960: 61 73 73 65 73 20 75 73 65 72 20 74 65 78 74 20  asses user text 
f970: 74 6f 20 50 72 6f 63 65 73 73 2e 72 75 6e 20 75  to Process.run u
f980: 6e 63 68 65 63 6b 65 64 2e 20 52 65 66 75 73 69  nchecked. Refusi
f990: 6e 67 20 4e 55 4c 20 61 74 20 74 68 65 20 65 64  ng NUL at the ed
f9a0: 67 65 20 28 43 67 69 2e 66 6f 72 6d 2c 20 43 6c  ge (Cgi.form, Cl
f9b0: 69 2c 20 4d 63 70 29 2c 20 6f 72 20 75 73 69 6e  i, Mcp), or usin
f9c0: 67 20 6f 6e 6c 79 20 74 68 65 20 66 69 72 73 74  g only the first
f9d0: 20 6c 69 6e 65 20 6f 66 20 65 2e 6d 65 73 73 61   line of e.messa
f9e0: 67 65 2c 20 77 6f 75 6c 64 20 66 69 78 20 69 74  ge, would fix it
f9f0: 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22  .".  },.  {.   "
fa00: 74 69 74 6c 65 22 3a 20 22 65 64 69 74 20 77 72  title": "edit wr
fa10: 69 74 65 73 20 6f 75 74 73 69 64 65 20 74 68 65  ites outside the
fa20: 20 63 68 65 63 6b 6f 75 74 20 74 68 72 6f 75 67   checkout throug
fa30: 68 20 61 20 64 61 6e 67 6c 69 6e 67 20 73 79 6d  h a dangling sym
fa40: 6c 69 6e 6b 22 2c 0a 20 20 20 22 73 65 76 65 72  link",.   "sever
fa50: 69 74 79 22 3a 20 22 68 69 67 68 22 2c 0a 20 20  ity": "high",.  
fa60: 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a   "reproduction":
fa70: 20 22 63 64 20 24 44 49 52 2f 63 6c 6f 6e 65 73   "cd $DIR/clones
fa80: 2f 69 76 79 2f 74 72 65 65 3b 20 6c 6e 20 2d 73  /ivy/tree; ln -s
fa90: 20 24 44 49 52 2f 4f 55 54 53 49 44 45 2d 77 72   $DIR/OUTSIDE-wr
faa0: 69 74 74 65 6e 2e 74 78 74 20 64 61 6e 67 6c 69  itten.txt dangli
fab0: 6e 67 3b 20 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20  ng; ocx2 --json 
fac0: 65 64 69 74 20 64 61 6e 67 6c 69 6e 67 20 5c 22  edit dangling \"
fad0: 5c 22 20 5c 22 70 6c 61 6e 74 65 64 20 6f 75 74  \" \"planted out
fae0: 73 69 64 65 5c 22 3b 20 63 61 74 20 24 44 49 52  side\"; cat $DIR
faf0: 2f 4f 55 54 53 49 44 45 2d 77 72 69 74 74 65 6e  /OUTSIDE-written
fb00: 2e 74 78 74 22 2c 0a 20 20 20 22 6f 62 73 65 72  .txt",.   "obser
fb10: 76 65 64 22 3a 20 22 7b 5c 22 6f 6b 5c 22 3a 74  ved": "{\"ok\":t
fb20: 72 75 65 2c 5c 22 74 6f 6f 6c 5c 22 3a 5c 22 65  rue,\"tool\":\"e
fb30: 64 69 74 5c 22 2c 2e 2e 2e 2c 5c 22 72 65 73 75  dit\",...,\"resu
fb40: 6c 74 5c 22 3a 7b 5c 22 74 65 78 74 5c 22 3a 5c  lt\":{\"text\":\
fb50: 22 70 6c 61 6e 74 65 64 20 6f 75 74 73 69 64 65  "planted outside
fb60: 5c 22 2c 2e 2e 2e 7d 7d 2e 20 24 44 49 52 2f 4f  \",...}}. $DIR/O
fb70: 55 54 53 49 44 45 2d 77 72 69 74 74 65 6e 2e 74  UTSIDE-written.t
fb80: 78 74 2c 20 6f 75 74 73 69 64 65 20 74 68 65 20  xt, outside the 
fb90: 63 68 65 63 6b 6f 75 74 2c 20 6e 6f 77 20 68 6f  checkout, now ho
fba0: 6c 64 73 20 27 70 6c 61 6e 74 65 64 20 6f 75 74  lds 'planted out
fbb0: 73 69 64 65 27 2e 20 46 6f 72 20 63 6f 6e 74 72  side'. For contr
fbc0: 61 73 74 2c 20 60 72 65 61 64 20 6c 69 76 65 60  ast, `read live`
fbd0: 2c 20 77 68 65 72 65 20 6c 69 76 65 20 69 73 20  , where live is 
fbe0: 61 20 73 79 6d 6c 69 6e 6b 20 74 6f 20 61 6e 20  a symlink to an 
fbf0: 65 78 69 73 74 69 6e 67 20 6f 75 74 73 69 64 65  existing outside
fc00: 20 66 69 6c 65 2c 20 69 73 20 72 65 66 75 73 65   file, is refuse
fc10: 64 3a 20 27 6c 69 76 65 20 6c 65 61 64 73 20 6f  d: 'live leads o
fc20: 75 74 73 69 64 65 20 74 68 65 20 63 68 65 63 6b  utside the check
fc30: 6f 75 74 27 2e 22 2c 0a 20 20 20 22 65 78 70 65  out'.",.   "expe
fc40: 63 74 65 64 22 3a 20 22 73 72 63 2f 6f 63 78 2f  cted": "src/ocx/
fc50: 63 68 65 63 6b 6f 75 74 5f 66 69 6c 65 73 2e 63  checkout_files.c
fc60: 72 3a 20 66 69 6c 65 73 20 61 72 65 20 6e 61 6d  r: files are nam
fc70: 65 64 20 27 62 79 20 69 74 73 20 70 61 74 68 20  ed 'by its path 
fc80: 66 72 6f 6d 20 74 68 65 20 63 68 65 63 6b 6f 75  from the checkou
fc90: 74 27 73 20 72 6f 6f 74 2c 20 6e 65 76 65 72 20  t's root, never 
fca0: 6f 75 74 73 69 64 65 20 69 74 27 2e 20 41 20 70  outside it'. A p
fcb0: 61 74 68 20 77 68 6f 73 65 20 6c 69 6e 6b 20 6c  ath whose link l
fcc0: 65 61 64 73 20 6f 75 74 73 69 64 65 20 73 68 6f  eads outside sho
fcd0: 75 6c 64 20 62 65 20 72 65 66 75 73 65 64 20 77  uld be refused w
fce0: 68 65 74 68 65 72 20 6f 72 20 6e 6f 74 20 69 74  hether or not it
fcf0: 73 20 74 61 72 67 65 74 20 65 78 69 73 74 73 20  s target exists 
fd00: 79 65 74 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22  yet.",.   "code"
fd10: 3a 20 22 73 72 63 2f 6f 63 78 2f 63 68 65 63 6b  : "src/ocx/check
fd20: 6f 75 74 5f 66 69 6c 65 73 2e 63 72 20 69 6e 73  out_files.cr ins
fd30: 69 64 65 21 3a 20 60 77 68 69 6c 65 20 21 46 69  ide!: `while !Fi
fd40: 6c 65 2e 65 78 69 73 74 73 3f 28 65 78 69 73 74  le.exists?(exist
fd50: 69 6e 67 29 3b 20 65 78 69 73 74 69 6e 67 20 3d  ing); existing =
fd60: 20 46 69 6c 65 2e 64 69 72 6e 61 6d 65 28 65 78   File.dirname(ex
fd70: 69 73 74 69 6e 67 29 60 20 66 6f 6c 6c 6f 77 73  isting)` follows
fd80: 20 6c 69 6e 6b 73 2c 20 73 6f 20 61 20 64 61 6e   links, so a dan
fd90: 67 6c 69 6e 67 20 6c 69 6e 6b 20 63 6f 75 6e 74  gling link count
fda0: 73 20 61 73 20 61 62 73 65 6e 74 2e 20 54 68 65  s as absent. The
fdb0: 20 63 68 65 63 6b 20 74 68 65 6e 20 63 6c 69 6d   check then clim
fdc0: 62 73 20 74 6f 20 74 68 65 20 63 68 65 63 6b 6f  bs to the checko
fdd0: 75 74 20 72 6f 6f 74 20 61 6e 64 20 70 61 73 73  ut root and pass
fde0: 65 73 2e 20 57 72 69 74 65 46 69 6c 65 23 70 65  es. WriteFile#pe
fdf0: 72 66 6f 72 6d 20 28 73 72 63 2f 6f 63 78 2f 63  rform (src/ocx/c
fe00: 6f 6d 6d 61 6e 64 73 2f 65 64 69 74 69 6e 67 2e  ommands/editing.
fe10: 63 72 3a 34 33 2d 34 36 29 20 74 68 65 6e 20 63  cr:43-46) then c
fe20: 61 6c 6c 73 20 46 69 6c 65 2e 77 72 69 74 65 28  alls File.write(
fe30: 66 75 6c 6c 29 2c 20 77 68 69 63 68 20 66 6f 6c  full), which fol
fe40: 6c 6f 77 73 20 74 68 65 20 6c 69 6e 6b 2e 20 54  lows the link. T
fe50: 68 65 20 66 69 78 20 69 73 20 46 69 6c 65 2e 73  he fix is File.s
fe60: 79 6d 6c 69 6e 6b 3f 20 2f 20 6c 73 74 61 74 20  ymlink? / lstat 
fe70: 6f 6e 20 65 61 63 68 20 70 61 72 74 20 6f 66 20  on each part of 
fe80: 74 68 65 20 70 61 74 68 2c 20 6f 72 20 72 65 66  the path, or ref
fe90: 75 73 69 6e 67 20 61 20 6c 69 6e 6b 20 61 74 20  using a link at 
fea0: 61 6e 79 20 70 61 72 74 2e 22 0a 20 20 7d 2c 0a  any part.".  },.
feb0: 20 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a 20    {.   "title": 
fec0: 22 46 72 6f 6d 20 61 20 63 6c 6f 6e 65 2c 20 74  "From a clone, t
fed0: 68 65 20 73 65 72 76 65 72 27 73 20 72 65 61 73  he server's reas
fee0: 6f 6e 20 66 6f 72 20 61 20 72 65 66 75 73 61 6c  on for a refusal
fef0: 20 69 73 20 64 72 6f 70 70 65 64 3a 20 27 74 68   is dropped: 'th
ff00: 65 20 73 65 72 76 65 72 20 61 6e 73 77 65 72 65  e server answere
ff10: 64 20 34 30 33 27 22 2c 0a 20 20 20 22 73 65 76  d 403'",.   "sev
ff20: 65 72 69 74 79 22 3a 20 22 6d 65 64 69 75 6d 22  erity": "medium"
ff30: 2c 0a 20 20 20 22 72 65 70 72 6f 64 75 63 74 69  ,.   "reproducti
ff40: 6f 6e 22 3a 20 22 63 64 20 24 44 49 52 2f 63 6c  on": "cd $DIR/cl
ff50: 6f 6e 65 73 2f 69 76 79 2f 74 72 65 65 3b 20 6f  ones/ivy/tree; o
ff60: 63 78 32 20 2d 2d 6a 73 6f 6e 20 72 65 63 65 69  cx2 --json recei
ff70: 70 74 20 2d 2d 61 72 74 69 66 61 63 74 73 20 2d  pt --artifacts -
ff80: 52 20 20 28 61 6c 73 6f 20 27 61 20 62 27 2c 20  R  (also 'a b', 
ff90: 6f 72 20 27 78 27 2a 32 30 30 30 30 30 20 74 68  or 'x'*200000 th
ffa0: 72 6f 75 67 68 20 4d 43 50 29 2e 20 57 69 74 68  rough MCP). With
ffb0: 20 61 20 73 74 61 6e 64 2d 69 6e 20 6f 6e 20 31   a stand-in on 1
ffc0: 32 37 2e 30 2e 30 2e 31 3a 31 38 39 34 32 20 74  27.0.0.1:18942 t
ffd0: 68 61 74 20 61 6e 73 77 65 72 73 20 34 30 33 20  hat answers 403 
ffe0: 77 69 74 68 20 7b 5c 22 6f 6b 5c 22 3a 66 61 6c  with {\"ok\":fal
fff0: 73 65 2c 2e 2e 2e 2c 5c 22 73 74 6f 70 70 65 64  se,...,\"stopped
10000 5c 22 3a 5c 22 61 20 72 65 61 73 6f 6e 20 74 68  \":\"a reason th
10010 65 20 73 65 72 76 65 72 20 67 61 76 65 5c 22 7d  e server gave\"}
10020 20 28 6f 74 74 6f 27 73 20 63 6c 6f 6e 65 20 72   (otto's clone r
10030 65 6d 6f 74 65 20 70 6f 69 6e 74 65 64 20 74 68  emote pointed th
10040 65 72 65 29 2c 20 72 75 6e 20 6f 63 78 32 20 2d  ere), run ocx2 -
10050 2d 6a 73 6f 6e 20 72 65 63 65 69 70 74 20 2f 20  -json receipt / 
10060 75 6e 61 75 64 69 74 65 64 2e 22 2c 0a 20 20 20  unaudited.",.   
10070 22 6f 62 73 65 72 76 65 64 22 3a 20 22 73 74 6f  "observed": "sto
10080 70 70 65 64 3a 20 5c 22 74 68 65 20 73 65 72 76  pped: \"the serv
10090 65 72 20 61 6e 73 77 65 72 65 64 20 34 30 33 5c  er answered 403\
100a0 22 2e 20 54 68 65 20 73 65 72 76 65 72 27 73 20  ". The server's 
100b0 6f 77 6e 20 4a 53 4f 4e 20 73 74 6f 70 70 65 64  own JSON stopped
100c0 20 28 27 72 65 63 65 69 70 74 3a 20 5c 22 2d 52   ('receipt: \"-R
100d0 5c 22 20 69 73 20 6e 6f 74 20 61 6e 20 61 72 74  \" is not an art
100e0 69 66 61 63 74 27 73 20 68 61 73 68 20 69 6e 20  ifact's hash in 
100f0 66 75 6c 6c 27 29 20 69 73 20 69 6e 20 74 68 65  full') is in the
10100 20 72 65 73 70 6f 6e 73 65 20 62 6f 64 79 20 62   response body b
10110 75 74 20 69 73 20 6e 6f 74 20 72 65 61 64 2e 20  ut is not read. 
10120 41 20 73 65 72 76 65 72 20 61 6e 73 77 65 72 20  A server answer 
10130 6f 66 20 7b 7d 20 67 69 76 65 73 20 5c 22 74 68  of {} gives \"th
10140 65 20 73 65 72 76 65 72 20 64 69 64 20 6e 6f 74  e server did not
10150 20 61 6e 73 77 65 72 20 69 74 3a 20 5c 22 20 77   answer it: \" w
10160 69 74 68 20 61 6e 20 65 6d 70 74 79 20 72 65 61  ith an empty rea
10170 73 6f 6e 2e 22 2c 0a 20 20 20 22 65 78 70 65 63  son.",.   "expec
10180 74 65 64 22 3a 20 22 54 68 65 20 72 75 6c 65 20  ted": "The rule 
10190 74 68 61 74 20 65 76 65 72 79 20 72 65 66 75 73  that every refus
101a0 61 6c 20 73 61 79 73 20 77 68 79 2e 20 54 68 65  al says why. The
101b0 20 34 30 33 20 62 6f 64 79 20 69 73 20 74 68 65   403 body is the
101c0 20 73 65 72 76 65 72 27 73 20 41 6e 73 77 65 72   server's Answer
101d0 20 4a 53 4f 4e 20 61 6e 64 20 63 61 72 72 69 65   JSON and carrie
101e0 73 20 73 74 6f 70 70 65 64 20 61 6e 64 20 6e 65  s stopped and ne
101f0 78 74 5f 73 74 65 70 2e 22 2c 0a 20 20 20 22 63  xt_step.",.   "c
10200 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f 73  ode": "src/ocx/s
10210 65 72 76 65 72 2e 63 72 20 41 73 6b 65 64 2e 61  erver.cr Asked.a
10220 6e 73 77 65 72 65 64 3a 20 60 72 61 69 73 65 20  nswered: `raise 
10230 52 65 66 75 73 65 64 2e 6e 65 77 28 5c 22 74 68  Refused.new(\"th
10240 65 20 73 65 72 76 65 72 20 61 6e 73 77 65 72 65  e server answere
10250 64 20 23 7b 72 65 73 70 6f 6e 73 65 2e 73 74 61  d #{response.sta
10260 74 75 73 5f 63 6f 64 65 7d 5c 22 29 20 75 6e 6c  tus_code}\") unl
10270 65 73 73 20 72 65 73 70 6f 6e 73 65 2e 73 75 63  ess response.suc
10280 63 65 73 73 3f 60 20 72 75 6e 73 20 62 65 66 6f  cess?` runs befo
10290 72 65 20 74 68 65 20 62 6f 64 79 20 69 73 20 72  re the body is r
102a0 65 61 64 2e 20 41 73 6b 53 65 72 76 65 72 52 65  ead. AskServerRe
102b0 63 65 69 70 74 73 23 70 65 72 66 6f 72 6d 20 28  ceipts#perform (
102c0 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73  src/ocx/commands
102d0 2f 72 65 63 65 69 70 74 2e 63 72 29 20 67 69 76  /receipt.cr) giv
102e0 65 73 20 60 74 68 65 20 73 65 72 76 65 72 20 64  es `the server d
102f0 69 64 20 6e 6f 74 20 61 6e 73 77 65 72 20 69 74  id not answer it
10300 3a 20 23 7b 61 6e 73 77 65 72 2e 73 74 6f 70 70  : #{answer.stopp
10310 65 64 7d 60 20 65 76 65 6e 20 77 68 65 6e 20 73  ed}` even when s
10320 74 6f 70 70 65 64 20 69 73 20 6e 69 6c 2e 22 0a  topped is nil.".
10330 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69 74    },.  {.   "tit
10340 6c 65 22 3a 20 22 41 20 72 65 6d 6f 74 65 20 74  le": "A remote t
10350 68 61 74 20 74 72 69 63 6b 6c 65 73 20 62 79 74  hat trickles byt
10360 65 73 20 73 74 61 6c 6c 73 20 63 6c 6f 6e 65 20  es stalls clone 
10370 61 73 6b 73 20 77 69 74 68 6f 75 74 20 6c 69 6d  asks without lim
10380 69 74 2c 20 69 6e 63 6c 75 64 69 6e 67 20 4d 43  it, including MC
10390 50 20 73 74 61 72 74 75 70 20 69 6e 20 61 20 63  P startup in a c
103a0 6c 6f 6e 65 22 2c 0a 20 20 20 22 73 65 76 65 72  lone",.   "sever
103b0 69 74 79 22 3a 20 22 6d 65 64 69 75 6d 22 2c 0a  ity": "medium",.
103c0 20 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e     "reproduction
103d0 22 3a 20 22 50 6f 69 6e 74 20 6f 74 74 6f 27 73  ": "Point otto's
103e0 20 63 6c 6f 6e 65 20 61 74 20 61 20 73 74 61 6e   clone at a stan
103f0 64 2d 69 6e 20 6f 6e 20 31 32 37 2e 30 2e 30 2e  d-in on 127.0.0.
10400 31 3a 31 38 39 34 32 20 74 68 61 74 20 73 65 6e  1:18942 that sen
10410 64 73 20 27 48 54 54 50 2f 31 2e 31 20 32 30 30  ds 'HTTP/1.1 200
10420 20 4f 4b 5c 5c 72 5c 5c 6e 43 6f 6e 74 65 6e 74   OK\\r\\nContent
10430 2d 4c 65 6e 67 74 68 3a 20 31 30 30 5c 5c 72 5c  -Length: 100\\r\
10440 5c 6e 5c 5c 72 5c 5c 6e 27 20 61 6e 64 20 74 68  \n\\r\\n' and th
10450 65 6e 20 6f 6e 65 20 62 79 74 65 20 65 76 65 72  en one byte ever
10460 79 20 35 20 73 2e 20 52 75 6e 3a 20 74 69 6d 65  y 5 s. Run: time
10470 6f 75 74 20 39 30 20 6f 63 78 32 20 2d 2d 6a 73  out 90 ocx2 --js
10480 6f 6e 20 72 65 63 65 69 70 74 20 2d 2d 61 72 74  on receipt --art
10490 69 66 61 63 74 73 20 3c 68 61 73 68 3e 20 2d 2d  ifacts <hash> --
104a0 63 61 70 61 62 69 6c 69 74 69 65 73 2d 6f 66 20  capabilities-of 
104b0 6f 74 74 6f 20 3b 20 74 69 6d 65 6f 75 74 20 39  otto ; timeout 9
104c0 30 20 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 75 6e  0 ocx2 --json un
104d0 61 75 64 69 74 65 64 20 3b 20 65 63 68 6f 20 27  audited ; echo '
104e0 7b 5c 22 6a 73 6f 6e 72 70 63 5c 22 3a 5c 22 32  {\"jsonrpc\":\"2
104f0 2e 30 5c 22 2c 5c 22 69 64 5c 22 3a 31 2c 5c 22  .0\",\"id\":1,\"
10500 6d 65 74 68 6f 64 5c 22 3a 5c 22 69 6e 69 74 69  method\":\"initi
10510 61 6c 69 7a 65 5c 22 2c 5c 22 70 61 72 61 6d 73  alize\",\"params
10520 5c 22 3a 7b 7d 7d 27 20 7c 20 74 69 6d 65 6f 75  \":{}}' | timeou
10530 74 20 34 30 20 6f 63 78 32 20 2d 2d 6d 63 70 22  t 40 ocx2 --mcp"
10540 2c 0a 20 20 20 22 6f 62 73 65 72 76 65 64 22 3a  ,.   "observed":
10550 20 22 72 65 63 65 69 70 74 20 61 6e 64 20 75 6e   "receipt and un
10560 61 75 64 69 74 65 64 20 77 65 72 65 20 6b 69 6c  audited were kil
10570 6c 65 64 20 62 79 20 74 69 6d 65 6f 75 74 20 61  led by timeout a
10580 74 20 39 30 20 73 20 77 69 74 68 6f 75 74 20 61  t 90 s without a
10590 6e 73 77 65 72 69 6e 67 2e 20 54 68 65 20 4d 43  nswering. The MC
105a0 50 20 73 65 72 76 65 72 20 6e 65 76 65 72 20 61  P server never a
105b0 6e 73 77 65 72 65 64 20 69 6e 69 74 69 61 6c 69  nswered initiali
105c0 7a 65 20 61 6e 64 20 77 61 73 20 6b 69 6c 6c 65  ze and was kille
105d0 64 20 61 74 20 34 30 20 73 2e 20 41 20 73 74 61  d at 40 s. A sta
105e0 6e 64 2d 69 6e 20 74 68 61 74 20 6e 65 76 65 72  nd-in that never
105f0 20 61 6e 73 77 65 72 73 20 61 74 20 61 6c 6c 20   answers at all 
10600 69 73 20 72 65 66 75 73 65 64 20 63 6f 72 72 65  is refused corre
10610 63 74 6c 79 20 61 66 74 65 72 20 31 30 2e 37 20  ctly after 10.7 
10620 73 20 28 27 52 65 61 64 20 74 69 6d 65 64 20 6f  s ('Read timed o
10630 75 74 27 29 2e 22 2c 0a 20 20 20 22 65 78 70 65  ut').",.   "expe
10640 63 74 65 64 22 3a 20 22 73 65 72 76 65 72 2e 63  cted": "server.c
10650 72 27 73 20 57 49 54 48 49 4e 2c 20 27 68 6f 77  r's WITHIN, 'how
10660 20 6c 6f 6e 67 20 74 68 65 20 73 65 72 76 65 72   long the server
10670 20 68 61 73 20 74 6f 20 61 6e 73 77 65 72 27 2c   has to answer',
10680 20 73 68 6f 75 6c 64 20 62 6f 75 6e 64 20 74 68   should bound th
10690 65 20 77 68 6f 6c 65 20 61 73 6b 2c 20 73 6f 20  e whole ask, so 
106a0 61 20 72 65 66 75 73 61 6c 20 63 6f 6d 65 73 20  a refusal comes 
106b0 62 61 63 6b 20 61 66 74 65 72 20 61 62 6f 75 74  back after about
106c0 20 31 30 20 73 2e 22 2c 0a 20 20 20 22 63 6f 64   10 s.",.   "cod
106d0 65 22 3a 20 22 73 72 63 2f 6f 63 78 2f 73 65 72  e": "src/ocx/ser
106e0 76 65 72 2e 63 72 20 41 73 6b 65 64 2e 61 6e 73  ver.cr Asked.ans
106f0 77 65 72 65 64 20 73 65 74 73 20 63 6f 6e 6e 65  wered sets conne
10700 63 74 5f 74 69 6d 65 6f 75 74 20 61 6e 64 20 72  ct_timeout and r
10710 65 61 64 5f 74 69 6d 65 6f 75 74 20 74 6f 20 57  ead_timeout to W
10720 49 54 48 49 4e 2e 20 42 6f 74 68 20 61 70 70 6c  ITHIN. Both appl
10730 79 20 70 65 72 20 72 65 61 64 2c 20 73 6f 20 65  y per read, so e
10740 76 65 72 79 20 62 79 74 65 20 72 65 73 74 61 72  very byte restar
10750 74 73 20 74 68 65 20 63 6c 6f 63 6b 2e 20 54 68  ts the clock. Th
10760 65 20 62 6f 64 79 20 63 6f 70 79 20 69 73 20 63  e body copy is c
10770 61 70 70 65 64 20 61 74 20 42 59 54 45 53 20 28  apped at BYTES (
10780 31 20 4d 69 42 29 20 62 75 74 20 68 61 73 20 6e  1 MiB) but has n
10790 6f 20 74 6f 74 61 6c 20 64 65 61 64 6c 69 6e 65  o total deadline
107a0 2e 20 45 6e 74 72 79 2e 69 64 65 6e 74 69 66 69  . Entry.identifi
107b0 65 64 20 28 73 72 63 2f 6f 63 78 2f 65 6e 74 72  ed (src/ocx/entr
107c0 79 2e 63 72 29 20 63 61 6c 6c 73 20 53 65 72 76  y.cr) calls Serv
107d0 65 72 3a 3a 41 73 6b 65 64 2e 63 61 70 61 62 69  er::Asked.capabi
107e0 6c 69 74 69 65 73 5f 61 74 20 62 65 66 6f 72 65  lities_at before
107f0 20 61 6e 20 4d 43 50 20 73 65 72 76 65 72 20 69   an MCP server i
10800 6e 20 61 20 63 6c 6f 6e 65 20 73 65 72 76 65 73  n a clone serves
10810 20 61 6e 79 74 68 69 6e 67 2e 22 0a 20 20 7d 2c   anything.".  },
10820 0a 20 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a  .  {.   "title":
10830 20 22 54 68 65 20 70 61 67 65 27 73 20 47 45 54   "The page's GET
10840 20 66 6f 72 6d 20 73 69 6c 65 6e 74 6c 79 20 64   form silently d
10850 72 6f 70 73 20 70 61 72 74 20 6f 66 20 61 20 6c  rops part of a l
10860 6f 6e 67 20 72 65 63 65 69 70 74 20 71 75 65 72  ong receipt quer
10870 79 3b 20 74 68 65 20 61 6e 73 77 65 72 20 69 73  y; the answer is
10880 20 6f 6b 3a 74 72 75 65 22 2c 0a 20 20 20 22 73   ok:true",.   "s
10890 65 76 65 72 69 74 79 22 3a 20 22 6d 65 64 69 75  everity": "mediu
108a0 6d 22 2c 0a 20 20 20 22 72 65 70 72 6f 64 75 63  m",.   "reproduc
108b0 74 69 6f 6e 22 3a 20 22 48 3d 34 30 20 53 48 41  tion": "H=40 SHA
108c0 33 20 68 61 73 68 65 73 20 6a 6f 69 6e 65 64 20  3 hashes joined 
108d0 62 79 20 27 2b 27 2e 20 63 75 72 6c 20 2d 73 20  by '+'. curl -s 
108e0 5c 22 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30  \"http://127.0.0
108f0 2e 31 3a 31 38 39 33 33 2f 65 78 74 2f 6f 63 78  .1:18933/ext/ocx
10900 32 2d 63 67 69 2f 72 65 63 65 69 70 74 3f 63 61  2-cgi/receipt?ca
10910 70 61 62 69 6c 69 74 69 65 73 5f 6f 66 3d 78 78  pabilities_of=xx
10920 78 78 78 78 78 78 78 78 78 78 78 26 6a 73 6f 6e  xxxxxxxxxxx&json
10930 3d 6f 6e 26 61 72 74 69 66 61 63 74 73 3d 24 48  =on&artifacts=$H
10940 5c 22 20 28 72 65 71 75 65 73 74 20 6c 69 6e 65  \" (request line
10950 20 32 36 36 30 20 62 79 74 65 73 29 2e 20 41 6c   2660 bytes). Al
10960 73 6f 20 65 63 68 6f 3f 6a 73 6f 6e 3d 6f 6e 26  so echo?json=on&
10970 77 6f 72 64 3d 3c 33 30 30 30 20 78 3e 26 6f 70  word=<3000 x>&op
10980 74 69 6f 6e 3d 61 66 74 65 72 2e 22 2c 0a 20 20  tion=after.",.  
10990 20 22 6f 62 73 65 72 76 65 64 22 3a 20 22 6f 6b   "observed": "ok
109a0 3a 74 72 75 65 20 77 69 74 68 20 33 30 20 61 72  :true with 30 ar
109b0 74 69 66 61 63 74 73 2c 20 31 30 20 6f 66 20 74  tifacts, 10 of t
109c0 68 65 20 34 30 20 61 73 6b 65 64 20 73 69 6c 65  he 40 asked sile
109d0 6e 74 6c 79 20 6d 69 73 73 69 6e 67 2e 20 65 63  ntly missing. ec
109e0 68 6f 20 72 65 74 75 72 6e 73 20 77 6f 72 64 20  ho returns word 
109f0 6f 66 20 31 39 36 33 20 63 68 61 72 61 63 74 65  of 1963 characte
10a00 72 73 20 61 6e 64 20 6f 70 74 69 6f 6e 20 61 62  rs and option ab
10a10 73 65 6e 74 2e 20 57 69 74 68 20 6f 74 68 65 72  sent. With other
10a20 20 70 61 64 64 69 6e 67 20 74 68 65 20 6c 61 73   padding the las
10a30 74 20 68 61 73 68 20 69 73 20 63 75 74 20 6d 69  t hash is cut mi
10a40 64 2d 77 61 79 20 61 6e 64 20 72 65 66 75 73 65  d-way and refuse
10a50 64 20 28 5c 22 62 39 30 35 36 5c 22 20 69 73 20  d (\"b9056\" is 
10a60 6e 6f 74 20 61 6e 20 61 72 74 69 66 61 63 74 27  not an artifact'
10a70 73 20 68 61 73 68 20 69 6e 20 66 75 6c 6c 29 2e  s hash in full).
10a80 20 46 6f 73 73 69 6c 20 32 2e 32 37 20 63 75 74   Fossil 2.27 cut
10a90 73 20 74 68 65 20 48 54 54 50 20 72 65 71 75 65  s the HTTP reque
10aa0 73 74 20 6c 69 6e 65 20 61 74 20 61 62 6f 75 74  st line at about
10ab0 20 32 30 30 30 20 62 79 74 65 73 2c 20 73 6f 20   2000 bytes, so 
10ac0 51 55 45 52 59 5f 53 54 52 49 4e 47 20 61 72 72  QUERY_STRING arr
10ad0 69 76 65 73 20 63 75 74 20 73 68 6f 72 74 2e 22  ives cut short."
10ae0 2c 0a 20 20 20 22 65 78 70 65 63 74 65 64 22 3a  ,.   "expected":
10af0 20 22 41 20 72 65 66 75 73 61 6c 2c 20 6f 72 20   "A refusal, or 
10b00 6e 6f 20 47 45 54 20 66 6f 72 6d 20 66 6f 72 20  no GET form for 
10b10 69 6e 70 75 74 20 74 68 61 74 20 63 61 6e 20 65  input that can e
10b20 78 63 65 65 64 20 46 6f 73 73 69 6c 27 73 20 6c  xceed Fossil's l
10b30 69 6e 65 2e 20 73 65 72 76 65 72 2e 63 72 20 61  ine. server.cr a
10b40 6c 72 65 61 64 79 20 6e 6f 74 65 73 20 27 61 20  lready notes 'a 
10b50 73 65 72 76 65 72 20 6d 61 79 20 72 65 66 75 73  server may refus
10b60 65 20 70 61 73 74 20 61 20 66 65 77 20 6b 69 6c  e past a few kil
10b70 6f 62 79 74 65 73 27 20 61 6e 64 20 6d 6f 76 65  obytes' and move
10b80 64 20 69 74 73 20 6f 77 6e 20 61 73 6b 73 20 74  d its own asks t
10b90 6f 20 50 4f 53 54 2c 20 62 75 74 20 74 68 65 20  o POST, but the 
10ba0 70 61 67 65 27 73 20 72 65 63 65 69 70 74 20 63  page's receipt c
10bb0 61 72 64 20 28 27 74 68 65 20 61 72 74 69 66 61  ard ('the artifa
10bc0 63 74 73 20 2e 2e 2e 20 73 65 70 61 72 61 74 65  cts ... separate
10bd0 64 20 62 79 20 73 70 61 63 65 73 27 29 20 73 74  d by spaces') st
10be0 69 6c 6c 20 73 75 62 6d 69 74 73 20 62 79 20 47  ill submits by G
10bf0 45 54 2e 22 2c 0a 20 20 20 22 63 6f 64 65 22 3a  ET.",.   "code":
10c00 20 22 73 72 63 2f 6f 63 78 2f 70 61 67 65 2e 63   "src/ocx/page.c
10c10 72 3a 32 33 31 3a 20 60 3c 66 6f 72 6d 20 6d 65  r:231: `<form me
10c20 74 68 6f 64 3d 5c 22 60 20 3c 3c 20 28 74 6f 6f  thod=\"` << (too
10c30 6c 2e 63 61 70 61 62 69 6c 69 74 69 65 73 5f 6e  l.capabilities_n
10c40 65 65 64 65 64 2e 65 6d 70 74 79 3f 20 3f 20 5c  eeded.empty? ? \
10c50 22 47 45 54 5c 22 20 3a 20 5c 22 50 4f 53 54 5c  "GET\" : \"POST\
10c60 22 29 60 2e 20 45 76 65 72 79 20 74 6f 6f 6c 20  ")`. Every tool 
10c70 74 68 61 74 20 6e 65 65 64 73 20 6e 6f 20 63 61  that needs no ca
10c80 70 61 62 69 6c 69 74 79 20 28 72 65 63 65 69 70  pability (receip
10c90 74 2c 20 75 6e 61 75 64 69 74 65 64 2c 20 65 63  t, unaudited, ec
10ca0 68 6f 29 20 70 6f 73 74 73 20 69 74 73 20 66 6f  ho) posts its fo
10cb0 72 6d 20 61 73 20 47 45 54 2e 20 73 72 63 2f 6f  rm as GET. src/o
10cc0 63 78 2f 63 67 69 2e 63 72 20 66 6f 72 6d 28 29  cx/cgi.cr form()
10cd0 20 63 61 6e 6e 6f 74 20 74 65 6c 6c 20 74 68 65   cannot tell the
10ce0 20 71 75 65 72 79 20 77 61 73 20 63 75 74 2e 22   query was cut."
10cf0 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22 74 69  .  },.  {.   "ti
10d00 74 6c 65 22 3a 20 22 72 65 63 65 69 70 74 20 6f  tle": "receipt o
10d10 66 20 61 62 6f 75 74 20 31 39 33 30 20 6f 72 20  f about 1930 or 
10d20 6d 6f 72 65 20 61 72 74 69 66 61 63 74 73 20 69  more artifacts i
10d30 6e 20 6f 6e 65 20 50 4f 53 54 20 69 73 20 72 65  n one POST is re
10d40 66 75 73 65 64 20 77 69 74 68 20 61 6e 20 69 6e  fused with an in
10d50 74 65 72 6e 61 6c 20 45 32 42 49 47 20 6d 65 73  ternal E2BIG mes
10d60 73 61 67 65 22 2c 0a 20 20 20 22 73 65 76 65 72  sage",.   "sever
10d70 69 74 79 22 3a 20 22 6c 6f 77 22 2c 0a 20 20 20  ity": "low",.   
10d80 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a 20  "reproduction": 
10d90 22 50 4f 53 54 20 68 74 74 70 3a 2f 2f 31 32 37  "POST http://127
10da0 2e 30 2e 30 2e 31 3a 31 38 39 33 33 2f 65 78 74  .0.0.1:18933/ext
10db0 2f 6f 63 78 32 2d 63 67 69 2f 72 65 63 65 69 70  /ocx2-cgi/receip
10dc0 74 20 77 69 74 68 20 62 6f 64 79 20 6a 73 6f 6e  t with body json
10dd0 3d 6f 6e 26 61 72 74 69 66 61 63 74 73 3d 3c 4e  =on&artifacts=<N
10de0 20 53 48 41 33 20 68 61 73 68 65 73 20 6a 6f 69   SHA3 hashes joi
10df0 6e 65 64 20 62 79 20 2b 3e 2c 20 4e 3d 31 39 30  ned by +>, N=190
10e00 30 2c 20 32 30 30 30 20 61 6e 64 20 35 30 30 30  0, 2000 and 5000
10e10 2e 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65 64  .",.   "observed
10e20 22 3a 20 22 4e 3d 31 39 30 30 3a 20 32 30 30 2c  ": "N=1900: 200,
10e30 20 31 39 30 30 20 61 6e 73 77 65 72 73 20 69 6e   1900 answers in
10e40 20 30 2e 30 34 20 73 2e 20 4e 3d 32 30 30 30 20   0.04 s. N=2000 
10e50 28 31 33 30 30 31 38 20 62 79 74 65 73 29 3a 20  (130018 bytes): 
10e60 34 30 33 2c 20 5c 22 72 65 61 64 5f 72 65 63 65  403, \"read_rece
10e70 69 70 74 73 20 66 61 69 6c 65 64 3a 20 45 72 72  ipts failed: Err
10e80 6f 72 20 65 78 65 63 75 74 69 6e 67 20 70 72 6f  or executing pro
10e90 63 65 73 73 3a 20 27 66 6f 73 73 69 6c 27 3a 20  cess: 'fossil': 
10ea0 41 72 67 75 6d 65 6e 74 20 6c 69 73 74 20 74 6f  Argument list to
10eb0 6f 20 6c 6f 6e 67 5c 22 2e 22 2c 0a 20 20 20 22  o long\".",.   "
10ec0 65 78 70 65 63 74 65 64 22 3a 20 22 45 69 74 68  expected": "Eith
10ed0 65 72 20 74 68 65 20 77 68 6f 6c 65 20 61 6e 73  er the whole ans
10ee0 77 65 72 2c 20 62 79 20 71 75 65 72 79 69 6e 67  wer, by querying
10ef0 20 69 6e 20 62 61 74 63 68 65 73 20 61 73 20 41   in batches as A
10f00 73 6b 65 64 20 64 6f 65 73 20 28 42 41 54 43 48  sked does (BATCH
10f10 3d 36 34 29 2c 20 6f 72 20 61 20 72 65 66 75 73  =64), or a refus
10f20 61 6c 20 74 68 61 74 20 6e 61 6d 65 73 20 74 68  al that names th
10f30 65 20 6c 69 6d 69 74 20 61 6e 64 20 77 68 61 74  e limit and what
10f40 20 74 6f 20 64 6f 2c 20 65 2e 67 2e 20 27 61 73   to do, e.g. 'as
10f50 6b 20 61 74 20 6d 6f 73 74 20 4e 20 61 72 74 69  k at most N arti
10f60 66 61 63 74 73 20 61 74 20 6f 6e 63 65 27 2e 22  facts at once'."
10f70 2c 0a 20 20 20 22 63 6f 64 65 22 3a 20 22 73 72  ,.   "code": "sr
10f80 63 2f 6f 63 78 2f 66 6f 73 73 69 6c 2f 73 61 69  c/ocx/fossil/sai
10f90 64 2e 63 72 3a 31 34 37 20 72 65 63 65 69 70 74  d.cr:147 receipt
10fa0 73 28 29 20 70 75 74 73 20 65 76 65 72 79 20 68  s() puts every h
10fb0 61 73 68 20 69 6e 74 6f 20 6f 6e 65 20 53 51 4c  ash into one SQL
10fc0 20 49 4e 28 2e 2e 2e 29 20 6c 69 73 74 2e 20 46   IN(...) list. F
10fd0 6f 73 73 69 6c 3a 3a 50 6c 61 63 65 23 71 75 65  ossil::Place#que
10fe0 72 79 20 70 61 73 73 65 73 20 74 68 61 74 20 53  ry passes that S
10ff0 51 4c 20 61 73 20 6f 6e 65 20 61 72 67 76 20 65  QL as one argv e
11000 6c 65 6d 65 6e 74 20 74 6f 20 60 66 6f 73 73 69  lement to `fossi
11010 6c 20 73 71 6c 60 20 28 73 72 63 2f 6f 63 78 2f  l sql` (src/ocx/
11020 66 6f 73 73 69 6c 2e 63 72 29 2e 20 4c 69 6e 75  fossil.cr). Linu
11030 78 20 63 61 70 73 20 61 20 73 69 6e 67 6c 65 20  x caps a single 
11040 61 72 67 75 6d 65 6e 74 20 61 74 20 31 32 38 20  argument at 128 
11050 4b 69 42 20 28 4d 41 58 5f 41 52 47 5f 53 54 52  KiB (MAX_ARG_STR
11060 4c 45 4e 29 2e 20 63 61 70 61 62 69 6c 69 74 69  LEN). capabiliti
11070 65 73 5f 6f 66 2c 20 77 69 6b 69 5f 72 65 61 64  es_of, wiki_read
11080 20 61 6e 64 20 61 75 64 69 74 20 63 68 65 63 6b   and audit check
11090 69 6e 20 66 61 69 6c 20 74 68 65 20 73 61 6d 65  in fail the same
110a0 20 77 61 79 20 6f 6e 20 61 20 32 30 30 30 30 30   way on a 200000
110b0 2d 63 68 61 72 61 63 74 65 72 20 76 61 6c 75 65  -character value
110c0 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20 22  .".  },.  {.   "
110d0 74 69 74 6c 65 22 3a 20 22 41 20 63 6c 6f 6e 65  title": "A clone
110e0 20 70 61 73 73 65 73 20 74 68 65 20 73 65 72 76   passes the serv
110f0 65 72 27 73 20 72 65 63 65 69 70 74 20 61 6e 73  er's receipt ans
11100 77 65 72 20 74 68 72 6f 75 67 68 20 75 6e 63 68  wer through unch
11110 65 63 6b 65 64 22 2c 0a 20 20 20 22 73 65 76 65  ecked",.   "seve
11120 72 69 74 79 22 3a 20 22 6c 6f 77 22 2c 0a 20 20  rity": "low",.  
11130 20 22 72 65 70 72 6f 64 75 63 74 69 6f 6e 22 3a   "reproduction":
11140 20 22 53 74 61 6e 64 2d 69 6e 20 6f 6e 20 31 32   "Stand-in on 12
11150 37 2e 30 2e 30 2e 31 3a 31 38 39 34 32 20 61 6e  7.0.0.1:18942 an
11160 73 77 65 72 73 20 7b 5c 22 6f 6b 5c 22 3a 74 72  swers {\"ok\":tr
11170 75 65 2c 5c 22 74 6f 6f 6c 5c 22 3a 5c 22 72 65  ue,\"tool\":\"re
11180 63 65 69 70 74 5c 22 2c 2e 2e 2e 2c 5c 22 72 65  ceipt\",...,\"re
11190 73 75 6c 74 5c 22 3a 7b 5c 22 61 72 74 69 66 61  sult\":{\"artifa
111a0 63 74 73 5c 22 3a 5b 7b 5c 22 61 72 74 69 66 61  cts\":[{\"artifa
111b0 63 74 5c 22 3a 5c 22 7a 7a 5c 22 2c 5c 22 72 65  ct\":\"zz\",\"re
111c0 63 65 69 76 65 64 5c 22 3a 74 72 75 65 2c 5c 22  ceived\":true,\"
111d0 73 65 6e 64 65 72 5c 22 3a 5c 22 6f 77 6e 65 72  sender\":\"owner
111e0 5c 22 2c 5c 22 63 61 70 61 62 69 6c 69 74 69 65  \",\"capabilitie
111f0 73 5c 22 3a 5c 22 73 5c 22 2c 2e 2e 2e 7d 5d 2c  s\":\"s\",...}],
11200 5c 22 75 73 65 72 5c 22 3a 7b 5c 22 75 73 65 72  \"user\":{\"user
11210 5c 22 3a 5c 22 6f 74 74 6f 5c 22 2c 5c 22 63 61  \":\"otto\",\"ca
11220 70 61 62 69 6c 69 74 69 65 73 5c 22 3a 5c 22 73  pabilities\":\"s
11230 5c 22 7d 7d 7d 2e 20 46 72 6f 6d 20 6f 74 74 6f  \"}}}. From otto
11240 27 73 20 63 6c 6f 6e 65 3a 20 6f 63 78 32 20 2d  's clone: ocx2 -
11250 2d 6a 73 6f 6e 20 72 65 63 65 69 70 74 20 2d 2d  -json receipt --
11260 61 72 74 69 66 61 63 74 73 20 32 39 62 30 61 33  artifacts 29b0a3
11270 30 61 30 35 35 31 32 64 30 33 61 32 61 62 61 34  0a05512d03a2aba4
11280 31 37 66 31 37 36 37 61 65 35 66 36 38 34 37 36  17f1767ae5f68476
11290 33 35 66 39 30 34 32 38 34 64 30 30 65 37 62 38  35f904284d00e7b8
112a0 64 61 64 65 64 65 32 35 62 31 20 2d 2d 63 61 70  dadede25b1 --cap
112b0 61 62 69 6c 69 74 69 65 73 2d 6f 66 20 6f 74 74  abilities-of ott
112c0 6f 22 2c 0a 20 20 20 22 6f 62 73 65 72 76 65 64  o",.   "observed
112d0 22 3a 20 22 72 63 3d 30 2c 20 6f 6b 3a 74 72 75  ": "rc=0, ok:tru
112e0 65 2e 20 54 68 65 20 61 6e 73 77 65 72 20 69 73  e. The answer is
112f0 20 66 6f 72 20 61 72 74 69 66 61 63 74 20 5c 22   for artifact \"
11300 7a 7a 5c 22 2c 20 77 68 69 63 68 20 77 61 73 20  zz\", which was 
11310 6e 6f 74 20 61 73 6b 65 64 20 61 6e 64 20 69 73  not asked and is
11320 20 6e 6f 74 20 61 20 68 61 73 68 2c 20 61 6e 64   not a hash, and
11330 20 64 6f 65 73 20 6e 6f 74 20 6d 65 6e 74 69 6f   does not mentio
11340 6e 20 74 68 65 20 68 61 73 68 20 74 68 61 74 20  n the hash that 
11350 77 61 73 20 61 73 6b 65 64 2e 20 41 20 73 74 61  was asked. A sta
11360 6e 64 2d 69 6e 20 67 69 76 69 6e 67 20 63 61 70  nd-in giving cap
11370 61 62 69 6c 69 74 69 65 73 20 5c 22 73 3b 20 72  abilities \"s; r
11380 6d 20 2d 72 66 20 2f 5c 22 20 69 73 20 72 65 66  m -rf /\" is ref
11390 75 73 65 64 20 61 73 20 5c 22 46 6f 73 73 69 6c  used as \"Fossil
113a0 27 73 20 63 61 70 61 62 69 6c 69 74 69 65 73 20  's capabilities 
113b0 61 72 65 20 6c 65 74 74 65 72 73 20 61 6e 64 20  are letters and 
113c0 64 69 67 69 74 73 2c 20 6e 6f 74 20 2e 2e 2e 5c  digits, not ...\
113d0 22 2c 20 77 69 74 68 6f 75 74 20 73 61 79 69 6e  ", without sayin
113e0 67 20 74 68 65 20 73 65 72 76 65 72 20 73 65 6e  g the server sen
113f0 74 20 69 74 2e 22 2c 0a 20 20 20 22 65 78 70 65  t it.",.   "expe
11400 63 74 65 64 22 3a 20 22 54 68 65 20 63 6c 6f 6e  cted": "The clon
11410 65 20 73 68 6f 75 6c 64 20 63 68 65 63 6b 20 74  e should check t
11420 68 61 74 20 74 68 65 20 61 6e 73 77 65 72 20 63  hat the answer c
11430 6f 76 65 72 73 20 65 78 61 63 74 6c 79 20 74 68  overs exactly th
11440 65 20 61 72 74 69 66 61 63 74 73 20 61 73 6b 65  e artifacts aske
11450 64 2c 20 69 6e 20 6f 72 64 65 72 2c 20 65 61 63  d, in order, eac
11460 68 20 61 20 66 75 6c 6c 20 68 61 73 68 2c 20 61  h a full hash, a
11470 6e 64 20 73 68 6f 75 6c 64 20 73 61 79 20 74 68  nd should say th
11480 61 74 20 61 20 6d 61 6c 66 6f 72 6d 65 64 20 61  at a malformed a
11490 6e 73 77 65 72 20 63 61 6d 65 20 66 72 6f 6d 20  nswer came from 
114a0 74 68 65 20 73 65 72 76 65 72 2e 22 2c 0a 20 20  the server.",.  
114b0 20 22 63 6f 64 65 22 3a 20 22 73 72 63 2f 6f 63   "code": "src/oc
114c0 78 2f 63 6f 6d 6d 61 6e 64 73 2f 72 65 63 65 69  x/commands/recei
114d0 70 74 2e 63 72 20 52 65 63 65 69 70 74 43 6f 6d  pt.cr ReceiptCom
114e0 6d 61 6e 64 2e 61 73 6b 65 64 20 72 65 74 75 72  mand.asked retur
114f0 6e 73 20 60 4f 75 74 70 75 74 2e 6e 65 77 28 61  ns `Output.new(a
11500 72 74 69 66 61 63 74 73 3a 20 73 65 72 76 65 72  rtifacts: server
11510 2e 61 72 74 69 66 61 63 74 73 2c 20 75 73 65 72  .artifacts, user
11520 3a 20 73 65 72 76 65 72 2e 75 73 65 72 2c 20 61  : server.user, a
11530 73 6b 65 64 3a 20 70 6c 61 69 6e 29 60 20 77 69  sked: plain)` wi
11540 74 68 6f 75 74 20 63 6f 6d 70 61 72 69 6e 67 20  thout comparing 
11550 61 67 61 69 6e 73 74 20 69 6e 70 75 74 2e 61 72  against input.ar
11560 74 69 66 61 63 74 73 2e 22 0a 20 20 7d 2c 0a 20  tifacts.".  },. 
11570 20 7b 0a 20 20 20 22 74 69 74 6c 65 22 3a 20 22   {.   "title": "
11580 54 68 65 20 43 4c 49 20 63 61 6e 6e 6f 74 20 70  The CLI cannot p
11590 61 73 73 20 61 20 72 65 71 75 69 72 65 64 20 76  ass a required v
115a0 61 6c 75 65 20 74 68 61 74 20 73 74 61 72 74 73  alue that starts
115b0 20 77 69 74 68 20 27 2d 2d 27 2c 20 61 6e 64 20   with '--', and 
115c0 68 61 73 20 6e 6f 20 65 6e 64 2d 6f 66 2d 6f 70  has no end-of-op
115d0 74 69 6f 6e 73 20 6d 61 72 6b 65 72 22 2c 0a 20  tions marker",. 
115e0 20 20 22 73 65 76 65 72 69 74 79 22 3a 20 22 6c    "severity": "l
115f0 6f 77 22 2c 0a 20 20 20 22 72 65 70 72 6f 64 75  ow",.   "reprodu
11600 63 74 69 6f 6e 22 3a 20 22 63 64 20 24 44 49 52  ction": "cd $DIR
11610 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74 72 65 65  /clones/ivy/tree
11620 3b 20 6f 63 78 32 20 2d 2d 6a 73 6f 6e 20 72 65  ; ocx2 --json re
11630 61 64 20 2d 2d 77 65 69 72 64 20 3b 20 6f 63 78  ad --weird ; ocx
11640 32 20 2d 2d 6a 73 6f 6e 20 65 63 68 6f 20 2d 2d  2 --json echo --
11650 20 2d 2d 68 65 6c 70 22 2c 0a 20 20 20 22 6f 62   --help",.   "ob
11660 73 65 72 76 65 64 22 3a 20 22 5c 22 6f 63 78 32  served": "\"ocx2
11670 3a 20 72 65 61 64 20 68 61 73 20 6e 6f 20 6f 70  : read has no op
11680 74 69 6f 6e 20 2d 2d 77 65 69 72 64 5c 22 20 61  tion --weird\" a
11690 6e 64 20 5c 22 65 63 68 6f 20 68 61 73 20 6e 6f  nd \"echo has no
116a0 20 6f 70 74 69 6f 6e 20 2d 2d 5c 22 2e 20 41 20   option --\". A 
116b0 62 61 72 65 20 77 6f 72 64 20 73 74 61 72 74 69  bare word starti
116c0 6e 67 20 77 69 74 68 20 27 2d 2d 27 20 69 73 20  ng with '--' is 
116d0 61 6c 77 61 79 73 20 72 65 61 64 20 61 73 20 61  always read as a
116e0 6e 20 6f 70 74 69 6f 6e 2c 20 61 6e 64 20 27 2d  n option, and '-
116f0 2d 27 20 69 73 20 6e 6f 74 20 75 6e 64 65 72 73  -' is not unders
11700 74 6f 6f 64 2e 20 4f 6e 65 20 64 61 73 68 20 69  tood. One dash i
11710 73 20 66 69 6e 65 3a 20 60 72 65 61 64 20 2d 52  s fine: `read -R
11720 60 20 67 69 76 65 73 20 5c 22 6e 6f 20 66 69 6c  ` gives \"no fil
11730 65 20 2d 52 5c 22 2e 22 2c 0a 20 20 20 22 65 78  e -R\".",.   "ex
11740 70 65 63 74 65 64 22 3a 20 22 41 20 72 65 71 75  pected": "A requ
11750 69 72 65 64 20 76 61 6c 75 65 20 6c 69 6b 65 20  ired value like 
11760 61 20 66 69 6c 65 20 6e 61 6d 65 64 20 27 2d 2d  a file named '--
11770 78 27 20 73 68 6f 75 6c 64 20 62 65 20 72 65 61  x' should be rea
11780 63 68 61 62 6c 65 2c 20 66 6f 72 20 65 78 61 6d  chable, for exam
11790 70 6c 65 20 61 66 74 65 72 20 27 2d 2d 27 2e 22  ple after '--'."
117a0 2c 0a 20 20 20 22 63 6f 64 65 22 3a 20 22 73 72  ,.   "code": "sr
117b0 63 2f 6f 63 78 2f 63 6c 69 2e 63 72 20 43 6c 69  c/ocx/cli.cr Cli
117c0 2e 72 65 61 64 3a 20 60 75 6e 6c 65 73 73 20 61  .read: `unless a
117d0 72 67 2e 73 74 61 72 74 73 5f 77 69 74 68 3f 28  rg.starts_with?(
117e0 5c 22 2d 2d 5c 22 29 60 20 74 72 65 61 74 73 20  \"--\")` treats 
117f0 65 76 65 72 79 20 73 75 63 68 20 77 6f 72 64 20  every such word 
11800 61 73 20 61 6e 20 6f 70 74 69 6f 6e 20 61 6e 64  as an option and
11810 20 68 61 73 20 6e 6f 20 27 2d 2d 27 20 63 61 73   has no '--' cas
11820 65 2e 22 0a 20 20 7d 2c 0a 20 20 7b 0a 20 20 20  e.".  },.  {.   
11830 22 74 69 74 6c 65 22 3a 20 22 54 65 73 74 20 65  "title": "Test e
11840 6e 76 69 72 6f 6e 6d 65 6e 74 3a 20 6f 63 78 32  nvironment: ocx2
11850 20 69 67 6e 6f 72 65 73 20 48 4f 4d 45 20 61 6e   ignores HOME an
11860 64 20 77 72 69 74 65 73 20 46 6f 73 73 69 6c 27  d writes Fossil'
11870 73 20 67 6c 6f 62 61 6c 20 63 6f 6e 66 69 67 20  s global config 
11880 69 6e 20 74 68 65 20 72 65 61 6c 20 61 63 63 6f  in the real acco
11890 75 6e 74 20 68 6f 6d 65 22 2c 0a 20 20 20 22 73  unt home",.   "s
118a0 65 76 65 72 69 74 79 22 3a 20 22 6c 6f 77 22 2c  everity": "low",
118b0 0a 20 20 20 22 72 65 70 72 6f 64 75 63 74 69 6f  .   "reproductio
118c0 6e 22 3a 20 22 52 75 6e 20 73 65 74 75 70 2e 73  n": "Run setup.s
118d0 68 2c 20 74 68 65 6e 20 63 75 72 6c 20 68 74 74  h, then curl htt
118e0 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a 50 4f  p://127.0.0.1:PO
118f0 52 54 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 2f  RT/ext/ocx2-cgi/
11900 73 74 61 74 75 73 3f 6a 73 6f 6e 3d 6f 6e 2c 20  status?json=on, 
11910 74 68 65 6e 20 72 75 6e 20 6f 63 78 32 20 66 72  then run ocx2 fr
11920 6f 6d 20 24 44 49 52 2f 65 6e 76 2e 73 68 2e 20  om $DIR/env.sh. 
11930 43 68 65 63 6b 3a 20 62 77 72 61 70 20 2d 2d 64  Check: bwrap --d
11940 65 76 2d 62 69 6e 64 20 2f 20 2f 20 2d 2d 62 69  ev-bind / / --bi
11950 6e 64 20 24 44 49 52 2f 61 63 63 74 20 2f 72 6f  nd $DIR/acct /ro
11960 6f 74 20 2d 2d 20 3c 73 65 72 76 65 72 3e 3b 20  ot -- <server>; 
11970 6f 6e 65 20 73 74 61 74 75 73 20 63 61 6c 6c 20  one status call 
11980 63 72 65 61 74 65 64 20 24 44 49 52 2f 61 63 63  created $DIR/acc
11990 74 2f 2e 66 6f 73 73 69 6c 2e 22 2c 0a 20 20 20  t/.fossil.",.   
119a0 22 6f 62 73 65 72 76 65 64 22 3a 20 22 74 6f 6f  "observed": "too
119b0 6c 73 2f 6f 63 78 32 2e 63 72 20 74 61 6b 65 73  ls/ocx2.cr takes
119c0 20 68 6f 6d 65 20 66 72 6f 6d 20 74 68 65 20 61   home from the a
119d0 63 63 6f 75 6e 74 20 64 61 74 61 62 61 73 65 20  ccount database 
119e0 28 53 79 73 74 65 6d 3a 3a 55 73 65 72 2e 66 69  (System::User.fi
119f0 6e 64 5f 62 79 28 69 64 3a 20 67 65 74 75 69 64  nd_by(id: getuid
11a00 29 2e 68 6f 6d 65 5f 64 69 72 65 63 74 6f 72 79  ).home_directory
11a10 29 2c 20 77 68 69 63 68 20 69 73 20 2f 72 6f 6f  ), which is /roo
11a20 74 20 68 65 72 65 2c 20 61 6e 64 20 46 6f 73 73  t here, and Foss
11a30 69 6c 2e 65 6e 76 20 70 61 73 73 65 73 20 74 68  il.env passes th
11a40 61 74 20 61 73 20 66 6f 73 73 69 6c 27 73 20 48  at as fossil's H
11a50 4f 4d 45 2e 20 45 76 65 72 79 20 66 6f 73 73 69  OME. Every fossi
11a60 6c 20 63 61 6c 6c 20 6f 63 78 32 20 6d 61 6b 65  l call ocx2 make
11a70 73 20 74 68 65 72 65 66 6f 72 65 20 72 65 61 64  s therefore read
11a80 73 20 61 6e 64 20 77 72 69 74 65 73 20 2f 72 6f  s and writes /ro
11a90 6f 74 2f 2e 66 6f 73 73 69 6c 2c 20 6e 6f 74 20  ot/.fossil, not 
11aa0 44 49 52 2f 68 6f 6d 65 2f 2e 66 6f 73 73 69 6c  DIR/home/.fossil
11ab0 2c 20 77 68 61 74 65 76 65 72 20 48 4f 4d 45 20  , whatever HOME 
11ac0 65 6e 76 2e 73 68 20 73 65 74 73 2e 20 54 6f 20  env.sh sets. To 
11ad0 73 74 61 79 20 69 6e 73 69 64 65 20 74 68 65 20  stay inside the 
11ae0 73 63 72 61 74 63 68 20 61 72 65 61 20 49 20 72  scratch area I r
11af0 61 6e 20 74 68 65 20 73 65 72 76 65 72 20 61 6e  an the server an
11b00 64 20 65 76 65 72 79 20 6f 63 78 32 20 63 61 6c  d every ocx2 cal
11b10 6c 20 75 6e 64 65 72 20 62 77 72 61 70 20 77 69  l under bwrap wi
11b20 74 68 20 61 20 73 63 72 61 74 63 68 20 64 69 72  th a scratch dir
11b30 65 63 74 6f 72 79 20 62 6f 75 6e 64 20 6f 76 65  ectory bound ove
11b40 72 20 2f 72 6f 6f 74 2e 22 2c 0a 20 20 20 22 65  r /root.",.   "e
11b50 78 70 65 63 74 65 64 22 3a 20 22 73 65 74 75 70  xpected": "setup
11b60 2e 73 68 27 73 20 75 73 61 67 65 20 6e 6f 74 65  .sh's usage note
11b70 73 20 73 61 79 20 27 45 76 65 72 79 20 66 6f 73  s say 'Every fos
11b80 73 69 6c 20 63 61 6c 6c 20 72 75 6e 73 20 77 69  sil call runs wi
11b90 74 68 20 6e 69 63 65 20 61 6e 64 20 48 4f 4d 45  th nice and HOME
11ba0 3d 44 49 52 2f 68 6f 6d 65 2c 20 73 6f 20 6e 6f  =DIR/home, so no
11bb0 20 7e 2f 2e 66 6f 73 73 69 6c 20 6f 75 74 73 69   ~/.fossil outsi
11bc0 64 65 20 44 49 52 20 69 73 20 74 6f 75 63 68 65  de DIR is touche
11bd0 64 27 2e 20 54 68 61 74 20 68 6f 6c 64 73 20 66  d'. That holds f
11be0 6f 72 20 73 65 74 75 70 27 73 20 6f 77 6e 20 66  or setup's own f
11bf0 6f 73 73 69 6c 20 63 61 6c 6c 73 20 62 75 74 20  ossil calls but 
11c00 6e 6f 74 20 66 6f 72 20 74 68 65 20 70 72 6f 67  not for the prog
11c10 72 61 6d 27 73 2e 22 2c 0a 20 20 20 22 63 6f 64  ram's.",.   "cod
11c20 65 22 3a 20 22 74 6f 6f 6c 73 2f 6f 63 78 32 2e  e": "tools/ocx2.
11c30 63 72 20 28 68 6f 6d 65 20 66 72 6f 6d 20 53 79  cr (home from Sy
11c40 73 74 65 6d 3a 3a 55 73 65 72 29 3b 20 73 72 63  stem::User); src
11c50 2f 6f 63 78 2f 66 6f 73 73 69 6c 2e 63 72 20 46  /ocx/fossil.cr F
11c60 6f 73 73 69 6c 2e 65 6e 76 28 68 6f 6d 65 29 2e  ossil.env(home).
11c70 20 54 68 65 20 66 69 78 20 62 65 6c 6f 6e 67 73   The fix belongs
11c80 20 69 6e 20 73 65 74 75 70 2e 73 68 3a 20 72 75   in setup.sh: ru
11c90 6e 20 74 68 65 20 73 65 72 76 65 72 20 61 6e 64  n the server and
11ca0 20 6f 63 78 32 20 77 69 74 68 20 74 68 65 20 61   ocx2 with the a
11cb0 63 63 6f 75 6e 74 20 68 6f 6d 65 20 72 65 64 69  ccount home redi
11cc0 72 65 63 74 65 64 2c 20 65 2e 67 2e 20 75 6e 64  rected, e.g. und
11cd0 65 72 20 62 77 72 61 70 2c 20 6f 72 20 64 6f 63  er bwrap, or doc
11ce0 75 6d 65 6e 74 20 74 68 65 20 65 66 66 65 63 74  ument the effect
11cf0 2e 22 0a 20 20 7d 0a 20 5d 2c 0a 20 22 74 72 69  .".  }. ],. "tri
11d00 65 64 22 3a 20 22 49 20 62 75 69 6c 74 20 61 20  ed": "I built a 
11d10 66 72 65 73 68 20 69 6e 73 74 61 6e 63 65 20 77  fresh instance w
11d20 69 74 68 20 73 65 74 75 70 2e 73 68 20 61 74 20  ith setup.sh at 
11d30 2e 2e 2e 2f 61 64 76 65 72 73 61 72 79 2f 69 6e  .../adversary/in
11d40 70 75 74 20 6f 6e 20 70 6f 72 74 20 31 38 39 33  put on port 1893
11d50 33 2e 20 49 20 72 65 73 74 61 72 74 65 64 20 69  3. I restarted i
11d60 74 73 20 73 65 72 76 65 72 20 75 6e 64 65 72 20  ts server under 
11d70 62 77 72 61 70 2c 20 62 69 6e 64 69 6e 67 20 61  bwrap, binding a
11d80 20 73 63 72 61 74 63 68 20 64 69 72 65 63 74 6f   scratch directo
11d90 72 79 20 6f 76 65 72 20 2f 72 6f 6f 74 20 28 73  ry over /root (s
11da0 65 65 20 74 68 65 20 6c 61 73 74 20 66 69 6e 64  ee the last find
11db0 69 6e 67 29 2c 20 61 6e 64 20 72 61 6e 20 65 76  ing), and ran ev
11dc0 65 72 79 20 6f 63 78 32 20 63 61 6c 6c 20 74 68  ery ocx2 call th
11dd0 65 20 73 61 6d 65 20 77 61 79 2e 20 45 61 63 68  e same way. Each
11de0 20 66 69 6e 64 69 6e 67 20 77 61 73 20 72 65 70   finding was rep
11df0 72 6f 64 75 63 65 64 20 6f 6e 20 74 68 69 73 20  roduced on this 
11e00 69 6e 73 74 61 6e 63 65 2c 20 6f 76 65 72 20 48  instance, over H
11e10 54 54 50 20 77 68 65 72 65 20 74 68 65 20 74 6f  TTP where the to
11e20 6f 6c 20 69 73 20 6f 6e 20 74 68 65 20 70 61 67  ol is on the pag
11e30 65 20 61 6e 64 20 77 69 74 68 20 74 68 65 20 43  e and with the C
11e40 47 49 20 72 75 6e 20 62 79 20 68 61 6e 64 20 66  GI run by hand f
11e50 6f 72 20 73 74 64 65 72 72 2e 20 49 20 61 6c 73  or stderr. I als
11e60 6f 20 75 73 65 64 20 61 20 73 65 63 6f 6e 64 20  o used a second 
11e70 73 63 72 61 74 63 68 20 63 6c 6f 6e 65 20 28 6f  scratch clone (o
11e80 74 74 6f 29 2c 20 61 6e 20 60 6f 63 78 32 20 2d  tto), an `ocx2 -
11e90 2d 6d 63 70 2d 68 74 74 70 60 20 73 65 72 76 65  -mcp-http` serve
11ea0 72 20 6f 6e 20 31 32 37 2e 30 2e 30 2e 31 3a 31  r on 127.0.0.1:1
11eb0 38 39 34 31 20 61 6e 64 20 61 20 73 74 61 6e 64  8941 and a stand
11ec0 2d 69 6e 20 6f 6e 20 31 32 37 2e 30 2e 30 2e 31  -in on 127.0.0.1
11ed0 3a 31 38 39 34 32 2e 20 49 20 73 65 6e 74 20 6e  :18942. I sent n
11ee0 6f 74 68 69 6e 67 20 74 6f 20 61 6e 79 20 6e 6f  othing to any no
11ef0 6e 2d 6c 6f 6f 70 62 61 63 6b 20 68 6f 73 74 2e  n-loopback host.
11f00 20 49 20 6d 61 64 65 20 6e 6f 20 63 6f 6d 6d 69   I made no commi
11f10 74 2c 20 70 6f 73 74 2c 20 73 74 61 67 65 20 6f  t, post, stage o
11f20 72 20 61 63 63 65 70 74 2c 20 61 6e 64 20 73 79  r accept, and sy
11f30 6e 63 65 64 20 6f 6e 6c 79 20 62 79 20 63 6c 6f  nced only by clo
11f40 6e 69 6e 67 20 66 72 6f 6d 20 74 68 65 20 73 63  ning from the sc
11f50 72 61 74 63 68 20 73 65 72 76 65 72 2e 20 50 6f  ratch server. Po
11f60 72 74 20 31 38 39 33 34 20 62 65 6c 6f 6e 67 73  rt 18934 belongs
11f70 20 74 6f 20 61 6e 6f 74 68 65 72 20 74 65 73 74   to another test
11f80 65 72 27 73 20 46 6f 73 73 69 6c 3a 20 74 68 72  er's Fossil: thr
11f90 65 65 20 6f 66 20 6d 79 20 50 4f 53 54 73 20 74  ee of my POSTs t
11fa0 6f 20 2f 6d 63 70 20 72 65 61 63 68 65 64 20 69  o /mcp reached i
11fb0 74 20 62 79 20 6d 69 73 74 61 6b 65 20 61 6e 64  t by mistake and
11fc0 20 67 6f 74 20 69 74 73 20 34 30 34 2c 20 61 6e   got its 404, an
11fd0 64 20 49 20 6d 6f 76 65 64 20 74 6f 20 31 38 39  d I moved to 189
11fe0 34 31 2e 20 57 72 69 74 65 73 20 49 20 6d 61 64  41. Writes I mad
11ff0 65 2c 20 61 6c 6c 20 69 6e 73 69 64 65 20 69 6e  e, all inside in
12000 70 75 74 2f 3a 20 6f 6e 65 20 66 69 6c 65 20 74  put/: one file t
12010 68 72 6f 75 67 68 20 74 68 65 20 73 79 6d 6c 69  hrough the symli
12020 6e 6b 20 66 69 6e 64 69 6e 67 2c 20 74 65 73 74  nk finding, test
12030 20 73 79 6d 6c 69 6e 6b 73 20 69 6e 20 69 76 79   symlinks in ivy
12040 27 73 20 63 68 65 63 6b 6f 75 74 2c 20 74 68 65  's checkout, the
12050 20 6f 74 74 6f 20 63 6c 6f 6e 65 20 77 69 74 68   otto clone with
12060 20 69 74 73 20 72 65 6d 6f 74 65 20 70 6f 69 6e   its remote poin
12070 74 65 64 20 61 74 20 74 68 65 20 73 74 61 6e 64  ted at the stand
12080 2d 69 6e 2c 20 61 6e 64 20 74 77 6f 20 72 75 6e  -in, and two run
12090 73 20 6f 66 20 74 68 65 20 73 65 63 72 65 74 20  s of the secret 
120a0 74 6f 6f 6c 20 77 69 74 68 20 76 61 6c 75 65 3d  tool with value=
120b0 25 30 61 20 61 6e 64 20 64 72 79 5f 72 75 6e 3d  %0a and dry_run=
120c0 74 72 75 65 2e 20 54 68 65 20 73 65 63 6f 6e 64  true. The second
120d0 20 6f 66 20 74 68 6f 73 65 20 73 65 63 72 65 74   of those secret
120e0 20 63 61 6c 6c 73 20 61 6e 73 77 65 72 65 64 20   calls answered 
120f0 6f 6b 3a 66 61 6c 73 65 20 27 61 20 73 65 63 72  ok:false 'a secr
12100 65 74 20 69 73 20 6f 6e 65 20 6c 69 6e 65 27 2c  et is one line',
12110 20 6e 6f 74 20 61 20 64 72 79 20 72 75 6e 2c 20   not a dry run, 
12120 73 6f 20 77 68 65 74 68 65 72 20 61 20 73 65 63  so whether a sec
12130 72 65 74 20 77 61 73 20 77 72 69 74 74 65 6e 20  ret was written 
12140 74 6f 20 74 68 65 20 73 63 72 61 74 63 68 20 72  to the scratch r
12150 65 6c 65 61 73 65 20 72 6f 6f 74 20 69 73 20 75  elease root is u
12160 6e 63 68 65 63 6b 65 64 2e 20 41 74 20 74 68 65  nchecked. At the
12170 20 65 6e 64 20 73 74 6f 70 2e 73 68 20 70 72 69   end stop.sh pri
12180 6e 74 65 64 20 27 73 74 6f 70 70 65 64 3a 20 6e  nted 'stopped: n
12190 6f 74 68 69 6e 67 20 73 65 72 76 65 73 20 2e 2e  othing serves ..
121a0 2e 2f 69 6e 70 75 74 2f 73 65 72 76 65 72 2f 72  ./input/server/r
121b0 65 70 6f 2e 66 6f 73 73 69 6c 27 2c 20 49 20 6b  epo.fossil', I k
121c0 69 6c 6c 65 64 20 74 68 65 20 73 74 61 6e 64 2d  illed the stand-
121d0 69 6e 73 20 61 6e 64 20 74 68 65 20 4d 43 50 20  ins and the MCP 
121e0 48 54 54 50 20 73 65 72 76 65 72 2c 20 61 6e 64  HTTP server, and
121f0 20 31 38 39 33 33 2c 20 31 38 39 34 31 20 61 6e   18933, 18941 an
12200 64 20 31 38 39 34 32 20 61 6c 6c 20 72 65 66 75  d 18942 all refu
12210 73 65 20 63 6f 6e 6e 65 63 74 69 6f 6e 73 2e 20  se connections. 
12220 44 75 72 69 6e 67 20 6f 6e 65 20 66 75 7a 7a 20  During one fuzz 
12230 72 75 6e 20 74 68 65 20 4d 43 50 20 48 54 54 50  run the MCP HTTP
12240 20 73 65 72 76 65 72 20 65 78 69 74 65 64 20 77   server exited w
12250 69 74 68 20 6e 6f 74 68 69 6e 67 20 6c 6f 67 67  ith nothing logg
12260 65 64 3b 20 74 68 61 74 20 64 69 64 20 6e 6f 74  ed; that did not
12270 20 68 61 70 70 65 6e 20 6f 6e 20 61 20 66 72 65   happen on a fre
12280 73 68 20 73 65 72 76 65 72 20 6f 72 20 6f 6e 20  sh server or on 
12290 61 20 72 65 72 75 6e 20 6f 66 20 74 68 65 20 73  a rerun of the s
122a0 61 6d 65 20 73 65 71 75 65 6e 63 65 2c 20 73 6f  ame sequence, so
122b0 20 49 20 6c 65 61 76 65 20 69 74 20 6f 75 74 2e   I leave it out.
122c0 5c 5c 6e 5c 5c 6e 57 68 61 74 20 68 65 6c 64 3a  \\n\\nWhat held:
122d0 5c 5c 6e 2d 20 50 61 74 68 20 74 72 61 76 65 72  \\n- Path traver
122e0 73 61 6c 3a 20 72 65 61 64 2c 20 66 69 6e 64 20  sal: read, find 
122f0 2d 2d 70 61 74 68 20 61 6e 64 20 65 64 69 74 20  --path and edit 
12300 72 65 66 75 73 65 20 2e 2e 2f 2e 2e 2f 2e 2e 2f  refuse ../../../
12310 70 61 73 73 77 6f 72 64 73 2e 74 78 74 2c 20 2f  passwords.txt, /
12320 65 74 63 2f 70 61 73 73 77 64 2c 20 27 27 20 61  etc/passwd, '' a
12330 6e 64 20 2e 2e 2f 2e 2e 2f 73 65 72 76 65 72 2f  nd ../../server/
12340 72 65 70 6f 2e 66 6f 73 73 69 6c 20 28 27 69 73  repo.fossil ('is
12350 20 6e 6f 74 20 61 20 70 61 74 68 20 69 6e 73 69   not a path insi
12360 64 65 20 74 68 65 20 63 68 65 63 6b 6f 75 74 27  de the checkout'
12370 29 2e 20 53 79 6d 6c 69 6e 6b 73 20 74 6f 20 65  ). Symlinks to e
12380 78 69 73 74 69 6e 67 20 6f 75 74 73 69 64 65 20  xisting outside 
12390 66 69 6c 65 73 20 6f 72 20 64 69 72 65 63 74 6f  files or directo
123a0 72 69 65 73 20 61 72 65 20 72 65 66 75 73 65 64  ries are refused
123b0 20 28 27 6c 65 61 64 73 20 6f 75 74 73 69 64 65   ('leads outside
123c0 20 74 68 65 20 63 68 65 63 6b 6f 75 74 27 29 2c   the checkout'),
123d0 20 61 6e 64 20 66 69 6e 64 20 64 6f 65 73 20 6e   and find does n
123e0 6f 74 20 66 6f 6c 6c 6f 77 20 74 68 65 6d 2e 5c  ot follow them.\
123f0 5c 6e 2d 20 4f 70 74 69 6f 6e 2d 6c 6f 6f 6b 69  \n- Option-looki
12400 6e 67 20 76 61 6c 75 65 73 20 28 2d 52 2c 20 2d  ng values (-R, -
12410 2d 68 65 6c 70 2c 20 2d 2d 75 73 65 72 3d 6f 77  -help, --user=ow
12420 6e 65 72 29 3a 20 65 76 65 72 79 20 43 47 49 20  ner): every CGI 
12430 61 6e 64 20 4d 43 50 20 66 69 65 6c 64 20 77 61  and MCP field wa
12440 73 20 72 65 66 75 73 65 64 20 77 69 74 68 20 61  s refused with a
12450 20 72 65 61 73 6f 6e 20 6f 72 20 74 72 65 61 74   reason or treat
12460 65 64 20 61 73 20 70 6c 61 69 6e 20 74 65 78 74  ed as plain text
12470 2e 20 74 68 72 65 61 64 2c 20 73 74 6f 70 2c 20  . thread, stop, 
12480 72 75 6e 20 61 6e 64 20 70 6f 73 74 20 2d 2d 74  run and post --t
12490 6f 20 6e 65 65 64 20 68 65 78 3b 20 73 65 63 72  o need hex; secr
124a0 65 74 20 61 6e 64 20 61 70 70 72 6f 76 65 20 63  et and approve c
124b0 68 65 63 6b 20 6e 61 6d 65 73 3b 20 61 75 64 69  heck names; audi
124c0 74 20 63 68 65 63 6b 73 20 74 68 65 20 76 65 72  t checks the ver
124d0 64 69 63 74 20 65 6e 75 6d 20 61 6e 64 20 74 68  dict enum and th
124e0 65 20 63 68 65 63 6b 2d 69 6e 20 6e 61 6d 65 2e  e check-in name.
124f0 5c 5c 6e 2d 20 54 68 65 20 77 65 62 20 70 61 67  \\n- The web pag
12500 65 20 65 73 63 61 70 65 73 20 48 54 4d 4c 20 61  e escapes HTML a
12510 6e 64 20 4d 61 72 6b 64 6f 77 6e 20 69 6e 20 61  nd Markdown in a
12520 6e 73 77 65 72 73 20 61 6e 64 20 66 6f 72 6d 20  nswers and form 
12530 76 61 6c 75 65 73 20 28 73 63 72 69 70 74 2c 20  values (script, 
12540 69 6d 67 20 6f 6e 65 72 72 6f 72 2c 20 6a 61 76  img onerror, jav
12550 61 73 63 72 69 70 74 3a 20 6c 69 6e 6b 73 2c 20  ascript: links, 
12560 73 76 67 20 6f 6e 6c 6f 61 64 2c 20 62 61 63 6b  svg onload, back
12570 74 69 63 6b 20 62 72 65 61 6b 6f 75 74 73 29 2e  tick breakouts).
12580 5c 5c 6e 2d 20 4a 53 4f 4e 3a 20 63 72 65 61 74  \\n- JSON: creat
12590 65 20 2d 2d 66 69 65 6c 64 73 20 72 65 66 75 73  e --fields refus
125a0 65 73 20 72 65 70 65 61 74 65 64 20 6e 61 6d 65  es repeated name
125b0 73 20 28 27 72 65 70 65 61 74 73 20 61 20 6e 61  s ('repeats a na
125c0 6d 65 27 2c 20 6e 65 73 74 65 64 20 74 6f 6f 29  me', nested too)
125d0 2c 20 61 72 72 61 79 73 2c 20 73 74 72 69 6e 67  , arrays, string
125e0 73 2c 20 6e 75 6d 62 65 72 73 2c 20 63 6f 6e 63  s, numbers, conc
125f0 61 74 65 6e 61 74 65 64 20 6f 62 6a 65 63 74 73  atenated objects
12600 20 61 6e 64 20 74 72 61 69 6c 69 6e 67 20 74 65   and trailing te
12610 78 74 2e 20 57 72 6f 6e 67 20 74 79 70 65 73 20  xt. Wrong types 
12620 69 6e 73 69 64 65 20 61 72 65 20 72 65 66 75 73  inside are refus
12630 65 64 20 77 69 74 68 20 74 68 65 20 74 79 70 65  ed with the type
12640 2e 20 4d 43 50 20 4a 53 4f 4e 20 6e 65 73 74 65  . MCP JSON neste
12650 64 20 31 30 30 30 30 30 20 64 65 65 70 20 69 73  d 100000 deep is
12660 20 61 6e 73 77 65 72 65 64 20 27 6e 6f 74 20 4a   answered 'not J
12670 53 4f 4e 27 20 61 6e 64 20 74 68 65 20 73 65 72  SON' and the ser
12680 76 65 72 20 6b 65 65 70 73 20 73 65 72 76 69 6e  ver keeps servin
12690 67 2e 5c 5c 6e 2d 20 4d 43 50 20 72 65 66 75 73  g.\\n- MCP refus
126a0 65 73 20 75 6e 6b 6e 6f 77 6e 20 61 72 67 75 6d  es unknown argum
126b0 65 6e 74 73 2c 20 77 72 6f 6e 67 20 74 79 70 65  ents, wrong type
126c0 73 20 28 5c 5c 5c 22 45 78 70 65 63 74 65 64 20  s (\\\"Expected 
126d0 53 74 72 69 6e 67 20 62 75 74 20 77 61 73 20 49  String but was I
126e0 6e 74 5c 5c 5c 22 29 2c 20 70 61 72 61 6d 73 20  nt\\\"), params 
126f0 74 68 61 74 20 61 72 65 20 6e 6f 74 20 61 6e 20  that are not an 
12700 6f 62 6a 65 63 74 20 61 6e 64 20 6e 61 6d 65 73  object and names
12710 20 74 68 61 74 20 61 72 65 20 6e 6f 74 20 73 74   that are not st
12720 72 69 6e 67 73 20 77 69 74 68 20 4a 53 4f 4e 2d  rings with JSON-
12730 52 50 43 20 65 72 72 6f 72 73 2c 20 61 6e 64 20  RPC errors, and 
12740 6b 65 65 70 73 20 73 65 72 76 69 6e 67 2e 20 41  keeps serving. A
12750 20 72 65 70 65 61 74 65 64 20 6b 65 79 20 69 6e   repeated key in
12760 20 4d 43 50 20 61 72 67 75 6d 65 6e 74 73 20 73   MCP arguments s
12770 69 6c 65 6e 74 6c 79 20 74 61 6b 65 73 20 74 68  ilently takes th
12780 65 20 6c 61 73 74 20 76 61 6c 75 65 2e 5c 5c 6e  e last value.\\n
12790 2d 20 53 65 72 76 65 72 2d 73 65 74 20 66 69 65  - Server-set fie
127a0 6c 64 73 20 61 72 65 20 72 65 66 75 73 65 64 3a  lds are refused:
127b0 20 72 6f 6f 74 20 66 6f 72 20 68 6f 6f 6b 2c 20   root for hook, 
127c0 75 6e 68 6f 6f 6b 2c 20 61 63 63 65 70 74 20 61  unhook, accept a
127d0 6e 64 20 72 6f 6c 6c 62 61 63 6b 2e 5c 5c 6e 2d  nd rollback.\\n-
127e0 20 41 20 50 4f 53 54 20 77 68 6f 73 65 20 43 6f   A POST whose Co
127f0 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 20 69 73 20  ntent-Length is 
12800 6d 6f 72 65 20 74 68 61 6e 20 69 74 73 20 62 6f  more than its bo
12810 64 79 20 69 73 20 72 65 66 75 73 65 64 20 62 79  dy is refused by
12820 20 46 6f 73 73 69 6c 20 77 69 74 68 20 34 30 30   Fossil with 400
12830 2e 20 4e 65 67 61 74 69 76 65 20 6c 65 6e 67 74  . Negative lengt
12840 68 73 20 61 6e 64 20 6d 75 6c 74 69 70 61 72 74  hs and multipart
12850 20 62 6f 64 69 65 73 20 67 65 74 20 61 20 72 65   bodies get a re
12860 61 73 6f 6e 65 64 20 34 30 33 2e 5c 5c 6e 2d 20  asoned 403.\\n- 
12870 41 20 33 30 20 4d 42 20 50 4f 53 54 20 74 6f 20  A 30 MB POST to 
12880 65 63 68 6f 20 61 6e 73 77 65 72 65 64 20 32 30  echo answered 20
12890 30 20 69 6e 20 33 20 73 3b 20 74 68 65 20 43 47  0 in 3 s; the CG
128a0 49 20 68 61 73 20 6e 6f 20 62 6f 64 79 20 6c 69  I has no body li
128b0 6d 69 74 2e 5c 5c 6e 2d 20 53 74 61 6e 64 2d 69  mit.\\n- Stand-i
128c0 6e 73 20 66 6f 72 20 74 68 65 20 63 6c 6f 6e 65  ns for the clone
128d0 27 73 20 61 73 6b 73 3a 20 63 6f 6e 6e 65 63 74  's asks: connect
128e0 69 6f 6e 20 63 6c 6f 73 65 64 2c 20 6e 6f 6e 2d  ion closed, non-
128f0 48 54 54 50 20 67 61 72 62 61 67 65 2c 20 48 54  HTTP garbage, HT
12900 4d 4c 2c 20 77 72 6f 6e 67 2d 73 68 61 70 65 20  ML, wrong-shape 
12910 4a 53 4f 4e 2c 20 35 30 30 2c 20 61 20 62 61 64  JSON, 500, a bad
12920 20 73 74 61 74 75 73 20 6c 69 6e 65 2c 20 61 20   status line, a 
12930 33 30 32 20 74 6f 20 61 6e 6f 74 68 65 72 20 70  302 to another p
12940 6f 72 74 20 28 6e 6f 74 20 66 6f 6c 6c 6f 77 65  ort (not followe
12950 64 29 2c 20 61 20 31 20 4d 69 42 2b 20 62 6f 64  d), a 1 MiB+ bod
12960 79 2c 20 63 68 75 6e 6b 65 64 20 77 69 74 68 6f  y, chunked witho
12970 75 74 20 65 6e 64 20 61 6e 64 20 61 20 32 20 4d  ut end and a 2 M
12980 42 20 68 65 61 64 65 72 20 65 61 63 68 20 67 61  B header each ga
12990 76 65 20 61 20 72 65 61 73 6f 6e 65 64 20 72 65  ve a reasoned re
129a0 66 75 73 61 6c 20 77 69 74 68 20 6e 6f 20 63 72  fusal with no cr
129b0 61 73 68 2e 20 41 20 73 65 72 76 65 72 20 74 68  ash. A server th
129c0 61 74 20 6e 65 76 65 72 20 61 6e 73 77 65 72 73  at never answers
129d0 20 69 73 20 72 65 66 75 73 65 64 20 61 66 74 65   is refused afte
129e0 72 20 31 30 2e 37 20 73 2e 5c 5c 6e 2d 20 41 6d  r 10.7 s.\\n- Am
129f0 62 69 67 75 6f 75 73 20 70 72 65 66 69 78 65 73  biguous prefixes
12a00 3a 20 74 68 65 20 72 65 70 6f 73 69 74 6f 72 79  : the repository
12a10 27 73 20 31 37 20 61 72 74 69 66 61 63 74 73 20  's 17 artifacts 
12a20 73 68 61 72 65 20 6e 6f 20 34 2d 63 68 61 72 61  share no 4-chara
12a30 63 74 65 72 20 70 72 65 66 69 78 2c 20 73 6f 20  cter prefix, so 
12a40 49 20 63 6f 75 6c 64 20 6f 6e 6c 79 20 63 68 65  I could only che
12a50 63 6b 20 62 79 20 72 65 61 64 69 6e 67 20 74 68  ck by reading th
12a60 65 20 63 6f 64 65 2e 20 4f 43 58 2e 6e 61 6d 65  e code. OCX.name
12a70 64 21 20 72 65 66 75 73 65 73 20 27 6e 61 6d 65  d! refuses 'name
12a80 73 20 6d 6f 72 65 20 74 68 61 6e 20 6f 6e 65 20  s more than one 
12a90 2e 2e 2e 3b 20 67 69 76 65 20 6d 6f 72 65 20 6f  ...; give more o
12aa0 66 20 69 74 27 2c 20 70 6f 73 74 5f 6e 61 6d 65  f it', post_name
12ab0 64 20 6c 69 6b 65 77 69 73 65 2c 20 72 65 63 6f  d likewise, reco
12ac0 72 64 73 5f 6e 61 6d 65 64 20 64 65 2d 64 75 70  rds_named de-dup
12ad0 6c 69 63 61 74 65 73 20 61 20 74 69 63 6b 65 74  licates a ticket
12ae0 20 66 6f 75 6e 64 20 62 79 20 62 6f 74 68 20 69   found by both i
12af0 74 73 20 69 64 20 61 6e 64 20 61 20 63 68 61 6e  ts id and a chan
12b00 67 65 2c 20 61 6e 64 20 74 68 65 20 30 30 30 30  ge, and the 0000
12b10 20 70 72 65 66 69 78 20 6e 61 6d 65 73 20 6e 6f   prefix names no
12b20 74 68 69 6e 67 2e 5c 5c 6e 2d 20 45 6d 70 74 79  thing.\\n- Empty
12b30 20 76 61 6c 75 65 73 3a 20 74 68 65 20 43 47 49   values: the CGI
12b40 20 74 72 65 61 74 73 20 61 6e 20 65 6d 70 74 79   treats an empty
12b50 20 66 69 65 6c 64 20 61 73 20 6e 6f 74 20 67 69   field as not gi
12b60 76 65 6e 2e 20 66 69 6e 64 20 27 27 20 67 69 76  ven. find '' giv
12b70 65 73 20 27 67 69 76 65 20 61 20 74 65 78 74 20  es 'give a text 
12b80 74 6f 20 66 69 6e 64 27 2c 20 61 20 73 65 63 72  to find', a secr
12b90 65 74 20 76 61 6c 75 65 20 6f 66 20 61 20 6e 65  et value of a ne
12ba0 77 6c 69 6e 65 20 67 69 76 65 73 20 27 6f 6e 65  wline gives 'one
12bb0 20 6c 69 6e 65 2c 20 6e 6f 74 20 65 6d 70 74 79   line, not empty
12bc0 27 2c 20 61 6e 64 20 72 65 63 65 69 70 74 20 77  ', and receipt w
12bd0 69 74 68 20 6e 6f 20 61 72 74 69 66 61 63 74 73  ith no artifacts
12be0 20 67 69 76 65 73 20 61 6e 20 65 6d 70 74 79 20   gives an empty 
12bf0 6c 69 73 74 2e 22 0a 7d 0a 00 00 00 00 00 00 00  list.".}........
12c00 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
12c10 2f 61 74 74 61 63 6b 2d 61 75 74 68 6f 72 69 74  /attack-authorit
12c20 79 2e 6a 73 6f 6e 00 00 00 00 00 00 00 00 00 00  y.json..........
12c30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12c40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12c50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12c60 00 00 00 00 30 30 30 30 36 34 34 00 30 30 30 30  ....0000644.0000
12c70 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
12c80 30 30 31 35 36 31 32 00 31 35 32 36 35 32 30 34  0015612.15265204
12c90 31 36 34 00 30 31 37 32 33 32 00 20 30 00 00 00  164.017232. 0...
12ca0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12cb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12cc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12cd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12ce0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12cf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d00 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
12d10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d20 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
12d30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12d90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12da0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12db0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12dc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12dd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12de0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12df0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
12e00 7b 0a 20 22 66 69 6e 64 69 6e 67 73 22 3a 20 5b  {. "findings": [
12e10 5d 2c 0a 20 22 74 72 69 65 64 22 3a 20 22 4e 4f  ],. "tried": "NO
12e20 20 41 55 54 48 4f 52 49 54 59 20 44 45 46 45 43   AUTHORITY DEFEC
12e30 54 20 46 4f 55 4e 44 2e 20 46 72 65 73 68 20 69  T FOUND. Fresh i
12e40 6e 73 74 61 6e 63 65 20 62 75 69 6c 74 20 77 69  nstance built wi
12e50 74 68 20 73 65 74 75 70 2e 73 68 20 61 74 20 61  th setup.sh at a
12e60 75 74 68 6f 72 69 74 79 2f 20 6f 6e 20 31 32 37  uthority/ on 127
12e70 2e 30 2e 30 2e 31 3a 31 38 39 33 31 20 28 65 78  .0.0.1:18931 (ex
12e80 69 74 65 64 20 5c 22 72 65 61 64 79 5c 22 29 2c  ited \"ready\"),
12e90 20 61 74 74 61 63 6b 65 64 2c 20 61 6e 64 20 73   attacked, and s
12ea0 74 6f 70 70 65 64 20 28 73 74 6f 70 2e 73 68 3a  topped (stop.sh:
12eb0 20 5c 22 73 74 6f 70 70 65 64 3a 20 6e 6f 74 68   \"stopped: noth
12ec0 69 6e 67 20 73 65 72 76 65 73 20 2e 2e 2e 2f 72  ing serves .../r
12ed0 65 70 6f 2e 66 6f 73 73 69 6c 5c 22 3b 20 70 6f  epo.fossil\"; po
12ee0 72 74 73 20 31 38 39 33 31 2f 31 38 39 33 32 2f  rts 18931/18932/
12ef0 31 38 39 33 35 2f 31 38 39 33 36 20 61 6c 6c 20  18935/18936 all 
12f00 72 65 66 75 73 65 3b 20 34 20 66 6f 72 75 6d 20  refuse; 4 forum 
12f10 70 6f 73 74 73 20 61 6e 64 20 6e 6f 20 72 75 6e  posts and no run
12f20 2d 75 73 65 72 73 20 77 72 69 74 74 65 6e 20 64  -users written d
12f30 75 72 69 6e 67 20 74 68 65 20 77 68 6f 6c 65 20  uring the whole 
12f40 73 65 73 73 69 6f 6e 20 e2 80 94 20 6e 6f 74 68  session — noth
12f50 69 6e 67 20 77 61 73 20 63 72 65 61 74 65 64 2c  ing was created,
12f60 20 70 6f 73 74 65 64 2c 20 73 79 6e 63 65 64 2c   posted, synced,
12f70 20 73 74 61 67 65 64 20 6f 72 20 61 63 63 65 70   staged or accep
12f80 74 65 64 3b 20 74 72 65 65 2f 73 72 63 20 61 6e  ted; tree/src an
12f90 64 20 74 72 65 65 2f 64 6f 63 73 20 6f 6e 6c 79  d tree/docs only
12fa0 20 72 65 61 64 29 2e 20 4f 6e 65 20 6f 70 65 72   read). One oper
12fb0 61 74 69 6f 6e 61 6c 20 65 72 72 6f 72 3a 20 73  ational error: s
12fc0 65 65 20 65 6e 64 2e 5c 6e 5c 6e 43 41 50 41 42  ee end.\n\nCAPAB
12fd0 49 4c 49 54 59 20 47 41 54 45 20 28 73 72 63 2f  ILITY GATE (src/
12fe0 6f 63 78 2f 63 6f 6d 6d 61 6e 64 2e 63 72 3a 32  ocx/command.cr:2
12ff0 31 34 20 72 65 66 75 73 61 6c 28 29 3a 20 6e 69  14 refusal(): ni
13000 6c 20 75 6e 6c 65 73 73 20 63 6f 6e 74 65 78 74  l unless context
13010 2e 63 61 70 61 62 69 6c 69 74 69 65 73 2e 61 6c  .capabilities.al
13020 6c 6f 77 73 3f 28 4e 45 45 44 53 29 29 2e 20 48  lows?(NEEDS)). H
13030 65 6c 64 20 66 6f 72 20 65 76 65 72 79 20 73 65  eld for every se
13040 6e 73 69 74 69 76 65 20 74 6f 6f 6c 2e 20 45 61  nsitive tool. Ea
13050 63 68 20 76 69 61 20 50 4f 53 54 2c 20 63 6f 6f  ch via POST, coo
13060 6b 69 65 20 70 65 72 20 75 73 65 72 2c 20 76 61  kie per user, va
13070 6c 69 64 20 52 65 66 65 72 65 72 20 60 2d 65 20  lid Referer `-e 
13080 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31  http://127.0.0.1
13090 3a 31 38 39 33 31 2f 60 2c 20 74 6f 20 2f 65 78  :18931/`, to /ex
130a0 74 2f 6f 63 78 32 2d 63 67 69 2f 54 4f 4f 4c 3f  t/ocx2-cgi/TOOL?
130b0 6a 73 6f 6e 3d 6f 6e 3a 5c 6e 2d 20 72 75 6e 2f  json=on:\n- run/
130c0 73 74 6f 70 2f 73 65 63 72 65 74 20 28 4e 45 45  stop/secret (NEE
130d0 44 53 20 61 29 20 61 73 20 6e 6f 62 6f 64 79 2c  DS a) as nobody,
130e0 20 6f 74 74 6f 2c 20 69 76 79 2c 20 72 69 74 61   otto, ivy, rita
130f0 20 2d 3e 20 48 54 54 50 20 34 30 33 20 6f 6b 3a   -> HTTP 403 ok:
13100 66 61 6c 73 65 20 5c 22 3c 75 73 65 72 3e 20 6c  false \"<user> l
13110 61 63 6b 73 20 77 68 61 74 20 3c 74 6f 6f 6c 3e  acks what <tool>
13120 20 6e 65 65 64 73 3a 20 61 6e 79 20 6f 66 20 74   needs: any of t
13130 68 65 20 46 6f 73 73 69 6c 20 63 61 70 61 62 69  he Fossil capabi
13140 6c 69 74 69 65 73 20 61 20 28 61 64 6d 69 6e 29  lities a (admin)
13150 3b 20 69 74 20 68 6f 6c 64 73 20 2e 2e 2e 5c 22  ; it holds ...\"
13160 2e 20 65 2e 67 2e 20 60 63 75 72 6c 20 2d 62 20  . e.g. `curl -b 
13170 6a 61 72 73 2f 72 69 74 61 20 2d 65 20 24 55 52  jars/rita -e $UR
13180 4c 2f 20 2d 58 20 50 4f 53 54 20 2d 2d 64 61 74  L/ -X POST --dat
13190 61 2d 75 72 6c 65 6e 63 6f 64 65 20 72 75 6e 3d  a-urlencode run=
131a0 30 61 34 66 20 24 50 2f 73 74 6f 70 3f 6a 73 6f  0a4f $P/stop?jso
131b0 6e 3d 6f 6e 60 20 2d 3e 20 34 30 33 2c 20 72 69  n=on` -> 403, ri
131c0 74 61 20 68 6f 6c 64 73 20 67 68 69 6a 6f 72 7a  ta holds ghijorz
131d0 52 2c 20 72 65 66 75 73 65 64 2e 20 5c 22 73 74  R, refused. \"st
131e0 6f 70 20 62 79 20 61 20 73 74 72 61 6e 67 65 72  op by a stranger
131f0 5c 22 2c 20 5c 22 61 70 70 72 6f 76 65 20 62 79  \", \"approve by
13200 20 6e 6f 6e 2d 61 64 6d 69 6e 5c 22 20 28 61 70   non-admin\" (ap
13210 70 72 6f 76 65 20 4e 45 45 44 53 20 61 29 20 62  prove NEEDS a) b
13220 6f 74 68 20 72 65 66 75 73 65 64 2e 5c 6e 2d 20  oth refused.\n- 
13230 68 6f 6f 6b 2f 75 6e 68 6f 6f 6b 2f 73 74 61 67  hook/unhook/stag
13240 65 2f 61 63 63 65 70 74 2f 72 6f 6c 6c 62 61 63  e/accept/rollbac
13250 6b 2f 65 78 70 6f 72 74 2f 69 6d 70 6f 72 74 20  k/export/import 
13260 28 4e 45 45 44 53 20 73 29 3a 20 61 64 61 6d 20  (NEEDS s): adam 
13270 68 6f 6c 64 73 20 61 64 6d 69 6e 20 28 61 29 20  holds admin (a) 
13280 62 75 74 20 4e 4f 54 20 73 65 74 75 70 20 28 73  but NOT setup (s
13290 29 20 61 6e 64 20 77 61 73 20 72 65 66 75 73 65  ) and was refuse
132a0 64 20 28 5c 22 61 64 61 6d 20 6c 61 63 6b 73 20  d (\"adam lacks 
132b0 77 68 61 74 20 68 6f 6f 6b 20 6e 65 65 64 73 3a  what hook needs:
132c0 20 2e 2e 2e 20 73 20 28 73 65 74 75 70 29 3b 20   ... s (setup); 
132d0 69 74 20 68 6f 6c 64 73 20 61 62 63 2e 2e 2e 41  it holds abc...A
132e0 44 5c 22 29 3b 20 69 76 79 2f 6e 6f 62 6f 64 79  D\"); ivy/nobody
132f0 20 72 65 66 75 73 65 64 20 6c 69 6b 65 77 69 73   refused likewis
13300 65 2e 20 4e 6f 74 65 20 61 63 63 65 70 74 2f 72  e. Note accept/r
13310 6f 6c 6c 62 61 63 6b 2f 65 78 70 6f 72 74 20 6e  ollback/export n
13320 65 65 64 20 61 20 50 4f 53 54 20 62 6f 64 79 20  eed a POST body 
13330 6f 72 20 46 6f 73 73 69 6c 20 69 74 73 65 6c 66  or Fossil itself
13340 20 72 65 74 75 72 6e 73 20 34 30 30 20 5c 22 6d   returns 400 \"m
13350 69 73 73 69 6e 67 20 43 4f 4e 54 45 4e 54 5f 4c  issing CONTENT_L
13360 45 4e 47 54 48 5c 22 20 62 65 66 6f 72 65 20 4f  ENGTH\" before O
13370 43 58 20 72 75 6e 73 20 28 46 6f 73 73 69 6c 20  CX runs (Fossil 
13380 62 65 68 61 76 69 6f 72 2c 20 6e 6f 74 20 4f 43  behavior, not OC
13390 58 29 2e 5c 6e 2d 20 57 65 62 20 69 64 65 6e 74  X).\n- Web ident
133a0 69 74 79 20 69 73 20 46 6f 73 73 69 6c 27 73 2c  ity is Fossil's,
133b0 20 6e 6f 74 20 74 68 65 20 63 6c 69 65 6e 74 27   not the client'
133c0 73 20 28 73 72 63 2f 6f 63 78 2f 63 67 69 2e 63  s (src/ocx/cgi.c
133d0 72 3a 76 69 65 77 65 72 20 72 65 61 64 73 20 46  r:viewer reads F
133e0 4f 53 53 49 4c 5f 55 53 45 52 2f 46 4f 53 53 49  OSSIL_USER/FOSSI
133f0 4c 5f 43 41 50 41 42 49 4c 49 54 49 45 53 20 66  L_CAPABILITIES f
13400 72 6f 6d 20 74 68 65 20 43 47 49 20 65 6e 76 29  rom the CGI env)
13410 2e 20 53 70 6f 6f 66 69 6e 67 20 72 65 66 75 73  . Spoofing refus
13420 65 64 3a 20 71 75 65 72 79 20 60 73 74 61 74 75  ed: query `statu
13430 73 3f 46 4f 53 53 49 4c 5f 55 53 45 52 3d 6f 77  s?FOSSIL_USER=ow
13440 6e 65 72 26 46 4f 53 53 49 4c 5f 43 41 50 41 42  ner&FOSSIL_CAPAB
13450 49 4c 49 54 49 45 53 3d 73 61 60 20 2d 3e 20 5c  ILITIES=sa` -> \
13460 22 73 74 61 74 75 73 20 68 61 73 20 6e 6f 20 61  "status has no a
13470 72 67 75 6d 65 6e 74 20 46 4f 53 53 49 4c 5f 55  rgument FOSSIL_U
13480 53 45 52 5c 22 20 28 74 72 65 61 74 65 64 20 61  SER\" (treated a
13490 73 20 75 6e 6b 6e 6f 77 6e 20 74 6f 6f 6c 20 61  s unknown tool a
134a0 72 67 29 3b 20 72 65 71 75 65 73 74 20 68 65 61  rg); request hea
134b0 64 65 72 73 20 46 4f 53 53 49 4c 5f 55 53 45 52  ders FOSSIL_USER
134c0 2f 46 4f 53 53 49 4c 5f 43 41 50 41 42 49 4c 49  /FOSSIL_CAPABILI
134d0 54 49 45 53 2f 52 45 4d 4f 54 45 5f 55 53 45 52  TIES/REMOTE_USER
134e0 20 69 67 6e 6f 72 65 64 20 28 73 74 69 6c 6c 20   ignored (still 
134f0 76 69 65 77 65 72 3d 6e 6f 62 6f 64 79 20 63 61  viewer=nobody ca
13500 70 73 20 67 68 6a 6f 72 7a 29 3b 20 62 6f 64 79  ps ghjorz); body
13510 20 66 69 65 6c 64 20 60 46 4f 53 53 49 4c 5f 43   field `FOSSIL_C
13520 41 50 41 42 49 4c 49 54 49 45 53 3d 61 60 20 6f  APABILITIES=a` o
13530 6e 20 72 75 6e 20 2d 3e 20 5c 22 72 75 6e 20 68  n run -> \"run h
13540 61 73 20 6e 6f 20 61 72 67 75 6d 65 6e 74 20 46  as no argument F
13550 4f 53 53 49 4c 5f 43 41 50 41 42 49 4c 49 54 49  OSSIL_CAPABILITI
13560 45 53 5c 22 2e 5c 6e 5c 6e 43 53 52 46 20 2f 20  ES\".\n\nCSRF / 
13570 47 45 54 20 28 73 72 63 2f 6f 63 78 2f 63 67 69  GET (src/ocx/cgi
13580 2e 63 72 3a 72 75 6e 20 2b 20 73 61 6d 65 5f 73  .cr:run + same_s
13590 69 74 65 5f 70 6f 73 74 3f 29 2e 20 48 65 6c 64  ite_post?). Held
135a0 3a 5c 6e 2d 20 47 45 54 20 74 6f 20 61 20 77 72  :\n- GET to a wr
135b0 69 74 69 6e 67 20 74 6f 6f 6c 20 77 69 74 68 20  iting tool with 
135c0 6a 73 6f 6e 3a 20 60 47 45 54 20 2f 63 72 65 61  json: `GET /crea
135d0 74 65 3f 6a 73 6f 6e 3d 6f 6e 26 6f 62 6a 65 63  te?json=on&objec
135e0 74 69 76 65 3d 70 77 6e 60 20 61 73 20 6f 77 6e  tive=pwn` as own
135f0 65 72 20 2d 3e 20 34 30 33 20 5c 22 63 72 65 61  er -> 403 \"crea
13600 74 65 20 63 68 61 6e 67 65 73 20 73 6f 6d 65 74  te changes somet
13610 68 69 6e 67 2c 20 73 6f 20 69 74 20 69 73 20 74  hing, so it is t
13620 61 6b 65 6e 20 6f 6e 6c 79 20 62 79 20 61 20 50  aken only by a P
13630 4f 53 54 20 66 72 6f 6d 20 74 68 69 73 20 73 69  OST from this si
13640 74 65 27 73 20 6f 77 6e 20 70 61 67 65 5c 22 2e  te's own page\".
13650 20 47 45 54 20 77 69 74 68 6f 75 74 20 6a 73 6f   GET without jso
13660 6e 20 72 65 74 75 72 6e 73 20 61 20 64 72 79 20  n returns a dry 
13670 72 75 6e 20 6f 6e 6c 79 20 28 6d 61 72 6b 64 6f  run only (markdo
13680 77 6e 20 5c 22 64 72 79 20 72 75 6e 5c 22 29 20  wn \"dry run\") 
13690 61 6e 64 20 77 72 6f 74 65 20 6e 6f 74 68 69 6e  and wrote nothin
136a0 67 20 28 66 6f 72 75 6d 20 70 6f 73 74 73 20 34  g (forum posts 4
136b0 20 62 65 66 6f 72 65 2f 61 66 74 65 72 29 2e 5c   before/after).\
136c0 6e 2d 20 50 4f 53 54 20 63 72 65 61 74 65 20 61  n- POST create a
136d0 73 20 6f 77 6e 65 72 20 77 69 74 68 20 4e 4f 20  s owner with NO 
136e0 52 65 66 65 72 65 72 2c 20 66 6f 72 65 69 67 6e  Referer, foreign
136f0 20 52 65 66 65 72 65 72 20 28 68 74 74 70 3a 2f   Referer (http:/
13700 2f 65 76 69 6c 2e 65 78 61 6d 70 6c 65 2f 29 2c  /evil.example/),
13710 20 73 75 62 64 6f 6d 61 69 6e 20 74 72 69 63 6b   subdomain trick
13720 20 28 68 74 74 70 3a 2f 2f 31 32 37 2e 30 2e 30   (http://127.0.0
13730 2e 31 3a 31 38 39 33 31 2e 65 76 69 6c 2e 65 78  .1:18931.evil.ex
13740 61 6d 70 6c 65 2f 29 2c 20 61 6e 64 20 75 73 65  ample/), and use
13750 72 69 6e 66 6f 20 74 72 69 63 6b 20 28 68 74 74  rinfo trick (htt
13760 70 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a 31 38  p://127.0.0.1:18
13770 39 33 31 40 65 76 69 6c 2e 65 78 61 6d 70 6c 65  931@evil.example
13780 2f 29 20 61 6c 6c 20 2d 3e 20 34 30 33 20 73 61  /) all -> 403 sa
13790 6d 65 20 72 65 66 75 73 61 6c 2e 20 54 68 65 20  me refusal. The 
137a0 73 74 61 72 74 73 5f 77 69 74 68 28 5c 22 3c 62  starts_with(\"<b
137b0 61 73 65 3e 2f 5c 22 29 20 63 68 65 63 6b 20 69  ase>/\") check i
137c0 73 20 6e 6f 74 20 66 6f 6f 6c 65 64 20 62 79 20  s not fooled by 
137d0 61 6e 79 20 6f 66 20 74 68 65 73 65 2e 5c 6e 2d  any of these.\n-
137e0 20 53 65 72 76 65 72 2d 73 65 74 20 66 69 65 6c   Server-set fiel
137f0 64 20 69 6e 6a 65 63 74 69 6f 6e 20 72 65 66 75  d injection refu
13800 73 65 64 3a 20 50 4f 53 54 20 61 63 63 65 70 74  sed: POST accept
13810 20 77 69 74 68 20 60 72 6f 6f 74 3d 2f 74 6d 70   with `root=/tmp
13820 2f 65 76 69 6c 60 20 2d 3e 20 6f 6b 3a 66 61 6c  /evil` -> ok:fal
13830 73 65 20 5c 22 2d 2d 72 6f 6f 74 20 69 73 20 73  se \"--root is s
13840 65 74 20 62 79 20 74 68 65 20 73 65 72 76 65 72  et by the server
13850 20 6f 6e 20 74 68 69 73 20 70 61 67 65 2c 20 6e   on this page, n
13860 6f 74 20 62 79 20 74 68 65 20 72 65 71 75 65 73  ot by the reques
13870 74 5c 22 20 28 73 72 63 2f 6f 63 78 2f 63 67 69  t\" (src/ocx/cgi
13880 2e 63 72 20 73 65 72 76 65 72 5f 73 65 74 29 2e  .cr server_set).
13890 5c 6e 5c 6e 63 6f 6c 6c 65 63 74 20 28 73 72 63  \n\ncollect (src
138a0 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73 2f 6c 6f  /ocx/commands/lo
138b0 67 69 6e 73 2e 63 72 3a 31 37 35 2c 20 4e 45 45  gins.cr:175, NEE
138c0 44 53 20 6e 6f 6e 65 2c 20 63 68 61 6e 67 65 73  DS none, changes
138d0 20 6e 6f 74 68 69 6e 67 29 2e 20 48 65 6c 64 3a   nothing). Held:
138e0 20 60 63 6f 6c 6c 65 63 74 3f 6c 6f 67 69 6e 3d   `collect?login=
138f0 6c 61 62 2d 32 26 63 6f 64 65 3d 77 72 6f 6e 67  lab-2&code=wrong
13900 63 6f 64 65 60 20 76 69 61 20 47 45 54 20 61 6e  code` via GET an
13910 64 20 76 69 61 20 50 4f 53 54 20 62 6f 74 68 20  d via POST both 
13920 2d 3e 20 5c 22 6c 61 62 2d 32 20 69 73 20 6e 6f  -> \"lab-2 is no
13930 74 20 61 70 70 72 6f 76 65 64 20 79 65 74 5c 22  t approved yet\"
13940 20 28 6e 6f 20 61 70 70 72 6f 76 65 64 20 6c 6f   (no approved lo
13950 67 69 6e 20 65 78 69 73 74 73 3b 20 6e 6f 20 70  gin exists; no p
13960 61 73 73 77 6f 72 64 20 6c 65 61 6b 65 64 29 2e  assword leaked).
13970 20 57 69 74 68 20 61 6e 20 61 70 70 72 6f 76 65   With an approve
13980 64 20 6c 6f 67 69 6e 20 61 20 77 72 6f 6e 67 20  d login a wrong 
13990 63 6f 64 65 20 68 69 74 73 20 5c 22 74 68 65 20  code hits \"the 
139a0 63 6f 64 65 20 69 73 20 6e 6f 74 20 74 68 65 20  code is not the 
139b0 6f 6e 65 20 3c 6c 6f 67 69 6e 3e 20 77 61 73 20  one <login> was 
139c0 61 70 70 72 6f 76 65 64 20 66 6f 72 5c 22 20 28  approved for\" (
139d0 6c 6f 67 69 6e 73 2e 63 72 3a 32 31 34 20 6b 65  logins.cr:214 ke
139e0 79 20 63 68 65 63 6b 29 2e 5c 6e 5c 6e 4d 43 50  y check).\n\nMCP
139f0 20 6f 76 65 72 20 48 54 54 50 20 28 2d 2d 6d 63   over HTTP (--mc
13a00 70 2d 68 74 74 70 2c 20 73 72 63 2f 6f 63 78 2f  p-http, src/ocx/
13a10 6d 63 70 5f 68 74 74 70 2e 63 72 29 2e 20 48 65  mcp_http.cr). He
13a20 6c 64 3a 20 62 69 6e 64 73 20 6c 6f 6f 70 62 61  ld: binds loopba
13a30 63 6b 20 6f 6e 6c 79 20 28 60 2d 2d 6d 63 70 2d  ck only (`--mcp-
13a40 68 74 74 70 20 30 2e 30 2e 30 2e 30 3a 31 38 39  http 0.0.0.0:189
13a50 33 32 60 20 2d 3e 20 5c 22 6c 69 73 74 65 6e 73  32` -> \"listens
13a60 20 6f 6e 20 74 68 69 73 20 68 6f 73 74 27 73 20   on this host's 
13a70 6c 6f 6f 70 62 61 63 6b 20 61 6c 6f 6e 65 2c 20  loopback alone, 
13a80 6e 6f 74 20 30 2e 30 2e 30 2e 30 5c 22 29 3b 20  not 0.0.0.0\"); 
13a90 47 45 54 20 2f 6d 63 70 20 2d 3e 20 34 30 35 2c  GET /mcp -> 405,
13aa0 20 6f 74 68 65 72 20 70 61 74 68 20 2d 3e 20 34   other path -> 4
13ab0 30 34 2e 20 4e 6f 20 70 65 72 2d 72 65 71 75 65  04. No per-reque
13ac0 73 74 20 61 75 74 68 20 62 79 20 64 65 73 69 67  st auth by desig
13ad0 6e 20 28 6c 6f 6f 70 62 61 63 6b 2b 74 75 6e 6e  n (loopback+tunn
13ae0 65 6c 29 2c 20 69 64 65 6e 74 69 74 79 20 66 69  el), identity fi
13af0 78 65 64 20 61 74 20 6c 61 75 6e 63 68 20 3d 20  xed at launch = 
13b00 74 68 65 20 6c 61 75 6e 63 68 69 6e 67 20 63 6f  the launching co
13b10 6e 74 65 78 74 3a 20 73 74 61 72 74 65 64 20 66  ntext: started f
13b20 72 6f 6d 20 61 20 6e 6f 2d 72 65 70 6f 73 69 74  rom a no-reposit
13b30 6f 72 79 20 64 69 72 2c 20 6f 63 78 5f 63 72 65  ory dir, ocx_cre
13b40 61 74 65 20 2d 3e 20 5c 22 74 68 69 73 20 63 61  ate -> \"this ca
13b50 6c 6c 65 72 20 6c 61 63 6b 73 20 77 68 61 74 20  ller lacks what 
13b60 63 72 65 61 74 65 20 6e 65 65 64 73 3a 20 2e 2e  create needs: ..
13b70 2e 20 61 20 28 61 64 6d 69 6e 29 3b 20 69 74 20  . a (admin); it 
13b80 68 6f 6c 64 73 20 6e 6f 6e 65 5c 22 2e 20 53 74  holds none\". St
13b90 61 72 74 65 64 20 66 72 6f 6d 20 69 76 79 27 73  arted from ivy's
13ba0 20 63 6c 6f 6e 65 2c 20 69 64 65 6e 74 69 74 79   clone, identity
13bb0 20 69 73 20 72 65 2d 72 65 61 64 20 66 72 6f 6d   is re-read from
13bc0 20 74 68 65 20 53 45 52 56 45 52 20 6e 6f 74 20   the SERVER not 
13bd0 74 68 65 20 63 6c 6f 6e 65 20 28 73 72 63 2f 6f  the clone (src/o
13be0 63 78 2f 65 6e 74 72 79 2e 63 72 3a 69 64 65 6e  cx/entry.cr:iden
13bf0 74 69 66 69 65 64 2c 20 6d 63 70 3f 20 62 72 61  tified, mcp? bra
13c00 6e 63 68 29 3a 20 73 74 61 74 75 73 20 73 68 6f  nch): status sho
13c10 77 65 64 20 6c 6f 67 69 6e 20 69 76 79 20 63 61  wed login ivy ca
13c20 70 73 20 5c 22 69 6f 67 6a 72 7a 68 5c 22 20 73  ps \"iogjrzh\" s
13c30 6f 75 72 63 65 20 5c 22 74 68 65 20 73 65 72 76  ource \"the serv
13c40 65 72 2c 20 61 73 20 69 74 73 20 72 65 63 65 69  er, as its recei
13c50 70 74 20 74 6f 6f 6c 20 73 61 79 73 5c 22 2c 20  pt tool says\", 
13c60 61 6e 64 20 6f 63 78 5f 63 72 65 61 74 65 20 2d  and ocx_create -
13c70 3e 20 72 65 66 75 73 65 64 20 5c 22 69 76 79 20  > refused \"ivy 
13c80 6c 61 63 6b 73 20 2e 2e 2e 20 61 20 28 61 64 6d  lacks ... a (adm
13c90 69 6e 29 3b 20 69 74 20 68 6f 6c 64 73 20 69 6f  in); it holds io
13ca0 67 6a 72 7a 68 5c 22 2e 20 42 6f 74 68 20 4d 43  gjrzh\". Both MC
13cb0 50 2d 48 54 54 50 20 73 65 72 76 65 72 73 20 49  P-HTTP servers I
13cc0 20 73 74 61 72 74 65 64 20 77 65 72 65 20 73 74   started were st
13cd0 6f 70 70 65 64 2e 5c 6e 5c 6e 43 4c 49 20 61 75  opped.\n\nCLI au
13ce0 74 68 6f 72 69 74 79 20 28 73 72 63 2f 6f 63 78  thority (src/ocx
13cf0 2f 65 6e 74 72 79 2e 63 72 3a 69 64 65 6e 74 69  /entry.cr:identi
13d00 66 69 65 64 29 2e 20 63 72 65 61 74 65 2f 72 75  fied). create/ru
13d10 6e 2f 73 74 6f 70 20 61 73 20 69 76 79 20 66 72  n/stop as ivy fr
13d20 6f 6d 20 68 65 72 20 63 6c 6f 6e 65 20 63 68 65  om her clone che
13d30 63 6b 6f 75 74 20 2d 3e 20 5c 22 61 63 74 73 20  ckout -> \"acts 
13d40 6f 6e 20 74 68 65 20 73 65 72 76 65 64 20 72 65  on the served re
13d50 70 6f 73 69 74 6f 72 79 3b 20 2e 2e 2e 2f 63 6c  pository; .../cl
13d60 6f 6e 65 73 2f 69 76 79 2f 74 72 65 65 20 69 73  ones/ivy/tree is
13d70 20 61 20 63 68 65 63 6b 6f 75 74 20 6f 66 20 2e   a checkout of .
13d80 2e 2e 2f 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 2c  ../clone.fossil,
13d90 20 77 68 69 63 68 20 74 68 69 73 20 72 65 6c 65   which this rele
13da0 61 73 65 27 73 20 68 6f 6f 6b 20 69 73 20 6e 6f  ase's hook is no
13db0 74 20 69 6e 73 74 61 6c 6c 65 64 20 69 6e 2c 20  t installed in, 
13dc0 73 6f 20 69 74 20 6d 61 79 20 62 65 20 61 20 63  so it may be a c
13dd0 6c 6f 6e 65 3a 20 6e 61 6d 65 20 74 68 65 20 73  lone: name the s
13de0 65 72 76 65 64 20 72 65 70 6f 73 69 74 6f 72 79  erved repository
13df0 20 77 69 74 68 20 2d 2d 72 65 70 6f 73 69 74 6f   with --reposito
13e00 72 79 20 6f 6e 20 69 74 73 20 68 6f 73 74 2c 20  ry on its host, 
13e10 6f 72 20 75 73 65 20 74 68 65 20 77 65 62 20 70  or use the web p
13e20 61 67 65 5c 22 2e 20 54 68 65 20 63 6c 6f 6e 65  age\". The clone
13e30 20 63 61 6e 6e 6f 74 20 73 74 61 6e 64 20 69 6e   cannot stand in
13e40 20 66 6f 72 20 74 68 65 20 73 65 72 76 65 64 20   for the served 
13e50 72 65 70 6f 2e 5c 6e 5c 6e 4e 4f 44 45 20 44 45  repo.\n\nNODE DE
13e60 43 49 53 49 4f 4e 20 47 41 54 45 20 28 73 72 63  CISION GATE (src
13e70 2f 6f 63 78 2f 64 65 63 69 73 69 6f 6e 73 2e 63  /ocx/decisions.c
13e80 72 29 2e 20 4e 6f 74 20 65 78 65 72 63 69 73 65  r). Not exercise
13e90 64 20 6c 69 76 65 20 62 65 63 61 75 73 65 20 77  d live because w
13ea0 72 69 74 69 6e 67 20 61 20 72 75 6e 20 61 72 74  riting a run art
13eb0 69 66 61 63 74 20 72 65 71 75 69 72 65 73 20 70  ifact requires p
13ec0 6f 73 74 69 6e 67 20 28 66 6f 72 62 69 64 64 65  osting (forbidde
13ed0 6e 20 62 79 20 74 68 65 20 74 61 73 6b 20 72 75  n by the task ru
13ee0 6c 65 73 29 20 61 6e 64 2c 20 6f 6e 20 74 68 69  les) and, on thi
13ef0 73 20 73 63 72 61 74 63 68 20 73 65 72 76 65 72  s scratch server
13f00 2c 20 6f 6e 6c 79 20 61 64 6d 69 6e 73 20 68 6f  , only admins ho
13f10 6c 64 20 66 6f 72 75 6d 2f 74 69 63 6b 65 74 20  ld forum/ticket 
13f20 61 70 70 65 6e 64 20 63 61 70 73 2c 20 73 6f 20  append caps, so 
13f30 61 20 6e 6f 6e 2d 61 64 6d 69 6e 20 63 61 6e 6e  a non-admin cann
13f40 6f 74 20 70 6c 61 63 65 20 61 20 72 75 6e 20 61  ot place a run a
13f50 72 74 69 66 61 63 74 20 61 74 20 61 6c 6c 2e 20  rtifact at all. 
13f60 43 6f 64 65 2d 72 65 76 69 65 77 65 64 3a 20 74  Code-reviewed: t
13f70 68 65 20 73 65 6e 64 65 72 27 73 20 69 64 65 6e  he sender's iden
13f80 74 69 74 79 20 61 6e 64 20 63 61 70 61 62 69 6c  tity and capabil
13f90 69 74 69 65 73 20 63 6f 6d 65 20 66 72 6f 6d 20  ities come from 
13fa0 74 68 65 20 73 65 72 76 65 72 27 73 20 72 65 63  the server's rec
13fb0 65 69 70 74 20 28 44 65 63 69 73 69 6f 6e 73 3a  eipt (Decisions:
13fc0 3a 53 65 6e 64 65 72 29 2c 20 6e 65 76 65 72 20  :Sender), never 
13fd0 66 72 6f 6d 20 74 68 65 20 72 75 6e 27 73 20 74  from the run's t
13fe0 65 78 74 2c 20 73 6f 20 61 20 72 75 6e 20 63 61  ext, so a run ca
13ff0 6e 6e 6f 74 20 66 6f 72 67 65 20 77 68 6f 20 73  nnot forge who s
14000 65 6e 74 20 69 74 2e 20 52 45 46 55 53 41 4c 53  ent it. REFUSALS
14010 20 72 6f 77 20 31 20 72 65 66 75 73 65 73 20 61   row 1 refuses a
14020 6e 79 20 72 75 6e 20 77 68 6f 73 65 20 73 65 6e  ny run whose sen
14030 64 65 72 20 6c 61 63 6b 73 20 61 64 6d 69 6e 2f  der lacks admin/
14040 73 65 74 75 70 20 61 6e 64 20 6c 61 63 6b 73 20  setup and lacks 
14050 52 20 28 61 6e 64 2c 20 68 6f 6c 64 69 6e 67 20  R (and, holding 
14060 6f 6e 6c 79 20 52 2c 20 72 65 66 75 73 65 73 20  only R, refuses 
14070 75 6e 6c 65 73 73 20 74 68 65 20 6e 6f 64 65 20  unless the node 
14080 6f 77 6e 65 72 27 73 20 62 6f 75 6e 64 73 20 66  owner's bounds f
14090 69 6c 65 20 61 6c 6c 6f 77 73 20 69 74 29 2e 20  ile allows it). 
140a0 52 6f 77 20 34 20 72 65 66 75 73 65 73 20 61 20  Row 4 refuses a 
140b0 72 75 6e 20 77 68 6f 73 65 20 70 72 6f 63 65 73  run whose proces
140c0 73 2e 75 73 65 72 20 69 73 20 61 20 6e 6f 64 65  s.user is a node
140d0 20 6c 6f 67 69 6e 20 6f 72 20 68 6f 6c 64 73 20   login or holds 
140e0 61 64 6d 69 6e 2f 73 65 74 75 70 2e 20 5c 22 41  admin/setup. \"A
140f0 20 72 75 6e 20 6e 61 6d 69 6e 67 20 69 74 73 65   run naming itse
14100 6c 66 20 61 73 20 69 74 73 20 6e 6f 64 65 5c 22  lf as its node\"
14110 20 61 6e 64 20 5c 22 61 20 72 75 6e 20 73 65 6e   and \"a run sen
14120 74 20 62 79 20 61 20 75 73 65 72 20 77 69 74 68  t by a user with
14130 6f 75 74 20 61 64 6d 69 6e 2f 73 65 74 75 70 2f  out admin/setup/
14140 52 5c 22 20 61 72 65 20 62 6f 74 68 20 63 6f 76  R\" are both cov
14150 65 72 65 64 20 62 79 20 74 68 65 73 65 20 72 6f  ered by these ro
14160 77 73 2e 20 63 72 65 61 74 65 20 69 74 73 65 6c  ws. create itsel
14170 66 20 72 65 2d 63 68 65 63 6b 73 20 61 73 20 61  f re-checks as a
14180 20 6e 6f 64 65 20 77 6f 75 6c 64 20 61 6e 64 20   node would and 
14190 72 65 66 75 73 65 73 20 61 6e 20 75 6e 61 75 74  refuses an unaut
141a0 68 6f 72 69 7a 65 64 20 70 61 74 74 65 72 6e 20  horized pattern 
141b0 66 65 74 63 68 3a 20 63 72 65 61 74 65 20 77 69  fetch: create wi
141c0 74 68 20 60 70 61 74 74 65 72 6e 3d 68 74 74 70  th `pattern=http
141d0 3a 2f 2f 31 32 37 2e 30 2e 30 2e 31 3a 31 38 39  ://127.0.0.1:189
141e0 33 31 2f 60 20 61 73 20 6e 6f 62 6f 64 79 2f 6f  31/` as nobody/o
141f0 74 74 6f 20 2d 3e 20 5c 22 63 72 65 61 74 65 20  tto -> \"create 
14200 66 65 74 63 68 65 73 20 61 20 70 61 74 74 65 72  fetches a patter
14210 6e 20 6f 6e 6c 79 20 66 6f 72 20 61 20 63 61 6c  n only for a cal
14220 6c 65 72 20 77 68 6f 20 6d 61 79 20 77 72 69 74  ler who may writ
14230 65 20 61 20 72 75 6e 5c 22 20 28 61 6e 74 69 2d  e a run\" (anti-
14240 53 53 52 46 2d 62 79 2d 75 6e 61 75 74 68 3b 20  SSRF-by-unauth; 
14250 73 72 63 2f 6f 63 78 2f 63 6f 6d 6d 61 6e 64 73  src/ocx/commands
14260 2f 63 72 65 61 74 65 2e 63 72 3a 32 31 36 29 2e  /create.cr:216).
14270 20 49 20 73 74 61 79 65 64 20 6f 6e 20 31 32 37   I stayed on 127
14280 2e 30 2e 30 2e 31 20 61 6e 64 20 64 69 64 20 6e  .0.0.1 and did n
14290 6f 74 20 61 74 74 65 6d 70 74 20 66 6f 72 65 69  ot attempt forei
142a0 67 6e 2d 68 6f 73 74 20 53 53 52 46 2e 5c 6e 5c  gn-host SSRF.\n\
142b0 6e 54 57 4f 20 44 4f 43 55 4d 45 4e 54 45 44 20  nTWO DOCUMENTED 
142c0 42 45 48 41 56 49 4f 52 53 20 77 6f 72 74 68 20  BEHAVIORS worth 
142d0 79 6f 75 72 20 6a 75 64 67 65 6d 65 6e 74 20 28  your judgement (
142e0 4e 4f 54 20 64 65 66 65 63 74 73 20 e2 80 94 20  NOT defects — 
142f0 62 6f 74 68 20 61 72 65 20 73 74 61 74 65 64 20  both are stated 
14300 69 6e 74 65 6e 74 2c 20 63 68 65 63 6b 65 64 20  intent, checked 
14310 61 67 61 69 6e 73 74 20 74 68 65 20 64 6f 63 73  against the docs
14320 29 3a 5c 6e 31 2e 20 43 4c 49 20 72 65 6c 65 61  ):\n1. CLI relea
14330 73 65 20 6f 70 73 20 6f 6e 20 61 20 63 6c 6f 6e  se ops on a clon
14340 65 20 62 79 70 61 73 73 20 74 68 65 20 73 65 74  e bypass the set
14350 75 70 20 67 61 74 65 2e 20 60 66 6f 73 73 69 6c  up gate. `fossil
14360 20 63 6c 6f 6e 65 20 2d 41 20 69 76 79 60 20 6d   clone -A ivy` m
14370 61 6b 65 73 20 69 76 79 20 6c 6f 63 61 6c 20 73  akes ivy local s
14380 65 74 75 70 2c 20 73 6f 20 66 72 6f 6d 20 69 76  etup, so from iv
14390 79 27 73 20 63 6c 6f 6e 65 20 60 6f 63 78 32 20  y's clone `ocx2 
143a0 72 6f 6c 6c 62 61 63 6b 2f 61 63 63 65 70 74 2f  rollback/accept/
143b0 73 74 61 67 65 20 2d 2d 64 72 79 2d 72 75 6e 60  stage --dry-run`
143c0 20 70 61 73 73 65 73 20 74 68 65 20 4e 45 45 44   passes the NEED
143d0 53 3d 73 20 67 61 74 65 20 28 73 74 6f 70 73 20  S=s gate (stops 
143e0 61 72 65 20 6f 70 65 72 61 74 69 6f 6e 61 6c 20  are operational 
143f0 e2 80 94 20 5c 22 74 68 65 72 65 20 69 73 20 6e  — \"there is n
14400 6f 20 70 72 65 76 69 6f 75 73 20 72 65 6c 65 61  o previous relea
14410 73 65 5c 22 20 2f 20 5c 22 6e 6f 74 68 69 6e 67  se\" / \"nothing
14420 20 69 73 20 6f 66 66 65 72 65 64 20 61 73 20 6e   is offered as n
14430 65 78 74 5c 22 20 e2 80 94 20 6e 65 76 65 72 20  ext\" — never 
14440 5c 22 6c 61 63 6b 73 20 73 65 74 75 70 5c 22 29  \"lacks setup\")
14450 2c 20 77 68 65 72 65 61 73 20 74 68 65 20 53 41  , whereas the SA
14460 4d 45 20 69 76 79 20 76 69 61 20 74 68 65 20 77  ME ivy via the w
14470 65 62 20 70 61 67 65 20 67 65 74 73 20 5c 22 69  eb page gets \"i
14480 76 79 20 6c 61 63 6b 73 20 2e 2e 2e 20 73 20 28  vy lacks ... s (
14490 73 65 74 75 70 29 5c 22 2e 20 54 68 69 73 20 69  setup)\". This i
144a0 73 20 69 6e 74 65 6e 64 65 64 3a 20 73 72 63 2f  s intended: src/
144b0 6f 63 78 2f 65 6e 74 72 79 2e 63 72 20 63 6f 6d  ocx/entry.cr com
144c0 6d 65 6e 74 20 5c 22 41 20 63 6c 6f 6e 65 20 6c  ment \"A clone l
144d0 69 73 74 73 20 69 74 73 20 6f 77 6e 20 63 6c 6f  ists its own clo
144e0 6e 65 72 20 61 73 20 73 65 74 75 70 2c 20 73 6f  ner as setup, so
144f0 20 69 6e 20 61 20 77 6f 72 6b 73 70 61 63 65 20   in a workspace 
14500 74 68 65 20 73 61 6e 64 62 6f 78 2c 20 6e 6f 74  the sandbox, not
14510 20 74 68 65 73 65 2c 20 69 73 20 77 68 61 74 20   these, is what 
14520 6c 69 6d 69 74 73 20 61 6e 20 61 67 65 6e 74 20  limits an agent 
14530 28 55 53 41 47 45 2e 6d 64 20 2e 2e 2e 29 5c 22  (USAGE.md ...)\"
14540 3b 20 4d 43 50 20 72 65 2d 72 65 61 64 73 20 73  ; MCP re-reads s
14550 65 72 76 65 72 20 63 61 70 73 20 62 75 74 20 43  erver caps but C
14560 4c 49 20 6b 65 65 70 73 20 74 68 65 20 63 6c 6f  LI keeps the clo
14570 6e 65 27 73 2e 20 43 6f 6e 73 65 71 75 65 6e 63  ne's. Consequenc
14580 65 3a 20 74 68 65 20 64 6f 63 73 27 20 5c 22 4f  e: the docs' \"O
14590 6e 6c 79 20 61 20 75 73 65 72 20 68 6f 6c 64 69  nly a user holdi
145a0 6e 67 20 73 65 74 75 70 20 6d 61 79 5c 22 20 69  ng setup may\" i
145b0 73 20 61 64 76 69 73 6f 72 79 20 6f 6e 20 74 68  s advisory on th
145c0 65 20 43 4c 49 20 e2 80 94 20 74 68 65 20 72 65  e CLI — the re
145d0 61 6c 20 62 6f 75 6e 64 61 72 79 20 66 6f 72 20  al boundary for 
145e0 72 65 6c 65 61 73 65 20 6f 70 73 20 69 73 20 66  release ops is f
145f0 69 6c 65 73 79 73 74 65 6d 20 6f 77 6e 65 72 73  ilesystem owners
14600 68 69 70 20 6f 66 20 74 68 65 20 72 65 6c 65 61  hip of the relea
14610 73 65 20 72 6f 6f 74 20 2b 20 74 68 65 20 73 61  se root + the sa
14620 6e 64 62 6f 78 2c 20 6e 6f 74 20 74 68 65 20 63  ndbox, not the c
14630 61 70 61 62 69 6c 69 74 79 2e 20 4f 6e 6c 79 20  apability. Only 
14640 62 69 74 65 73 20 69 66 20 61 20 6e 6f 6e 2d 73  bites if a non-s
14650 65 74 75 70 20 73 65 72 76 65 72 20 75 73 65 72  etup server user
14660 20 61 6c 72 65 61 64 79 20 68 61 73 20 73 68 65   already has she
14670 6c 6c 20 2b 20 77 72 69 74 65 20 61 63 63 65 73  ll + write acces
14680 73 20 74 6f 20 74 68 65 20 72 65 6c 65 61 73 65  s to the release
14690 20 72 6f 6f 74 2e 5c 6e 32 2e 20 72 65 63 65 69   root.\n2. recei
146a0 70 74 20 64 69 73 63 6c 6f 73 65 73 20 61 6e 79  pt discloses any
146b0 20 75 73 65 72 27 73 20 63 61 70 61 62 69 6c 69   user's capabili
146c0 74 69 65 73 20 74 6f 20 61 6e 79 20 72 65 61 64  ties to any read
146d0 65 72 2e 20 60 72 65 63 65 69 70 74 3f 63 61 70  er. `receipt?cap
146e0 61 62 69 6c 69 74 69 65 73 5f 6f 66 3d 6f 77 6e  abilities_of=own
146f0 65 72 60 20 61 73 20 6e 6f 62 6f 64 79 20 2d 3e  er` as nobody ->
14700 20 6f 6b 3a 74 72 75 65 20 5c 22 63 61 70 61 62   ok:true \"capab
14710 69 6c 69 74 69 65 73 5c 22 3a 5c 22 73 67 6a 6f  ilities\":\"sgjo
14720 72 7a 68 5c 22 2e 20 4d 61 74 63 68 65 73 20 64  rzh\". Matches d
14730 6f 63 73 2f 69 6e 74 65 72 66 61 63 65 73 2e 6d  ocs/interfaces.m
14740 64 3a 35 37 20 28 6e 65 65 64 73 20 6e 6f 20 63  d:57 (needs no c
14750 61 70 61 62 69 6c 69 74 79 3b 20 61 20 63 61 6c  apability; a cal
14760 6c 65 72 20 77 69 74 68 6f 75 74 20 52 65 61 64  ler without Read
14770 20 6f 20 67 65 74 73 20 6e 6f 6e 65 29 20 e2 80   o gets none) â€
14780 94 20 6e 6f 62 6f 64 79 20 68 6f 6c 64 73 20 6f  ” nobody holds o
14790 20 68 65 72 65 2c 20 73 6f 20 74 68 69 73 20 69   here, so this i
147a0 73 20 62 79 20 64 65 73 69 67 6e 3b 20 69 74 20  s by design; it 
147b0 69 73 20 61 6e 20 69 6e 66 6f 72 6d 61 74 69 6f  is an informatio
147c0 6e 2d 64 69 73 63 6c 6f 73 75 72 65 20 64 65 73  n-disclosure des
147d0 69 67 6e 20 63 68 6f 69 63 65 2c 20 6e 6f 74 20  ign choice, not 
147e0 61 20 62 75 67 2e 5c 6e 5c 6e 4f 50 45 52 41 54  a bug.\n\nOPERAT
147f0 49 4f 4e 41 4c 20 45 52 52 4f 52 20 28 6d 69 6e  IONAL ERROR (min
14800 65 29 3a 20 64 75 72 69 6e 67 20 63 6c 65 61 6e  e): during clean
14810 75 70 20 49 20 75 73 65 64 20 60 70 6b 69 6c 6c  up I used `pkill
14820 20 2d 66 20 27 6f 63 78 32 20 2d 2d 6d 63 70 2d   -f 'ocx2 --mcp-
14830 68 74 74 70 27 60 20 2f 20 60 70 73 7c 67 72 65  http'` / `ps|gre
14840 70 20 27 6f 63 78 32 20 2d 2d 6d 63 70 2d 68 74  p 'ocx2 --mcp-ht
14850 74 70 27 7c 6b 69 6c 6c 60 20 69 6e 73 74 65 61  tp'|kill` instea
14860 64 20 6f 66 20 6f 6e 6c 79 20 6d 79 20 72 65 63  d of only my rec
14870 6f 72 64 65 64 20 70 69 64 66 69 6c 65 73 2c 20  orded pidfiles, 
14880 61 6e 64 20 6b 69 6c 6c 65 64 20 74 77 6f 20 75  and killed two u
14890 6e 72 65 6c 61 74 65 64 20 60 6f 63 78 32 20 2d  nrelated `ocx2 -
148a0 2d 6d 63 70 2d 68 74 74 70 60 20 70 72 6f 63 65  -mcp-http` proce
148b0 73 73 65 73 20 6f 6e 20 70 6f 72 74 20 31 38 39  sses on port 189
148c0 34 31 20 62 65 6c 6f 6e 67 69 6e 67 20 74 6f 20  41 belonging to 
148d0 61 20 64 69 66 66 65 72 65 6e 74 20 73 61 6e 64  a different sand
148e0 62 6f 78 65 64 20 73 65 73 73 69 6f 6e 20 28 70  boxed session (p
148f0 61 74 68 20 2e 2e 2e 2f 61 64 76 65 72 73 61 72  ath .../adversar
14900 79 2f 69 6e 70 75 74 2f 61 63 63 74 2c 20 50 49  y/input/acct, PI
14910 44 73 20 32 32 35 30 38 34 30 2f 32 32 35 30 38  Ds 2250840/22508
14920 34 32 29 2e 20 4d 79 20 6f 77 6e 20 73 65 72 76  42). My own serv
14930 65 72 73 20 77 65 72 65 20 61 6c 72 65 61 64 79  ers were already
14940 20 64 6f 77 6e 2e 20 49 20 73 68 6f 75 6c 64 20   down. I should 
14950 68 61 76 65 20 6b 69 6c 6c 65 64 20 6f 6e 6c 79  have killed only
14960 20 74 68 65 20 50 49 44 73 20 69 6e 20 6d 63 70   the PIDs in mcp
14970 68 74 74 70 2e 70 69 64 2f 6d 63 70 68 74 74 70  http.pid/mcphttp
14980 32 2e 70 69 64 2e 22 0a 7d 0a 00 00 00 00 00 00  2.pid.".}.......
14990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
149f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14a00 61 64 76 65 72 73 61 72 79 2d 72 65 63 6f 72 64  adversary-record
14a10 2f 73 65 74 75 70 2e 73 68 00 00 00 00 00 00 00  /setup.sh.......
14a20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14a30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14a40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14a60 00 00 00 00 30 30 30 30 37 35 35 00 30 30 30 30  ....0000755.0000
14a70 30 30 30 00 30 30 30 30 30 30 30 00 30 30 30 30  000.0000000.0000
14a80 30 30 32 35 37 36 36 00 31 35 32 36 35 32 30 33  0025766.15265203
14a90 36 37 36 00 30 31 34 35 36 33 00 20 30 00 00 00  676.014563. 0...
14aa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14ab0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14ad0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14ae0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14af0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b00 00 75 73 74 61 72 20 20 00 72 6f 6f 74 00 00 00  .ustar  .root...
14b10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b20 00 00 00 00 00 00 00 00 00 72 6f 6f 74 00 00 00  .........root...
14b30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14b90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14ba0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14bc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14be0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
14c00 23 21 2f 62 69 6e 2f 73 68 0a 23 20 73 65 74 75  #!/bin/sh.# setu
14c10 70 2e 73 68 20 44 49 52 20 50 4f 52 54 0a 23 0a  p.sh DIR PORT.#.
14c20 23 20 4d 61 6b 65 73 20 61 20 66 72 65 73 68 20  # Makes a fresh 
14c30 4f 43 58 20 74 65 73 74 20 65 6e 76 69 72 6f 6e  OCX test environ
14c40 6d 65 6e 74 20 69 6e 20 44 49 52 20 28 77 68 69  ment in DIR (whi
14c50 63 68 20 6d 75 73 74 20 6e 6f 74 20 65 78 69 73  ch must not exis
14c60 74 20 6f 72 20 62 65 0a 23 20 65 6d 70 74 79 29  t or be.# empty)
14c70 2c 20 73 65 72 76 65 64 20 6f 6e 20 31 32 37 2e  , served on 127.
14c80 30 2e 30 2e 31 3a 50 4f 52 54 2c 20 74 68 65 20  0.0.1:PORT, the 
14c90 77 61 79 20 74 72 65 65 2f 73 70 65 63 2f 73 75  way tree/spec/su
14ca0 70 70 6f 72 74 2f 73 65 72 76 65 64 5f 6e 6f 64  pport/served_nod
14cb0 65 2e 63 72 0a 23 20 73 65 72 76 65 73 20 4f 43  e.cr.# serves OC
14cc0 58 20 74 6f 20 69 74 73 20 73 70 65 63 73 2c 20  X to its specs, 
14cd0 62 75 74 20 77 69 74 68 20 46 6f 73 73 69 6c 27  but with Fossil'
14ce0 73 20 6f 77 6e 20 73 65 72 76 65 72 20 72 75 6e  s own server run
14cf0 6e 69 6e 67 20 74 68 65 20 73 74 61 67 65 64 0a  ning the staged.
14d00 23 20 70 72 6f 67 72 61 6d 20 61 73 20 69 74 73  # program as its
14d10 20 65 78 74 20 70 61 67 65 20 2f 65 78 74 2f 6f   ext page /ext/o
14d20 63 78 32 2d 63 67 69 20 28 6e 6f 20 70 72 6f 78  cx2-cgi (no prox
14d30 79 20 69 6e 20 62 65 74 77 65 65 6e 3a 20 46 6f  y in between: Fo
14d40 73 73 69 6c 20 69 74 73 65 6c 66 0a 23 20 73 69  ssil itself.# si
14d50 67 6e 73 20 74 68 65 20 76 69 65 77 65 72 20 69  gns the viewer i
14d60 6e 20 61 6e 64 20 6e 61 6d 65 73 20 69 74 20 69  n and names it i
14d70 6e 20 46 4f 53 53 49 4c 5f 55 53 45 52 20 2f 20  n FOSSIL_USER / 
14d80 46 4f 53 53 49 4c 5f 43 41 50 41 42 49 4c 49 54  FOSSIL_CAPABILIT
14d90 49 45 53 29 2e 0a 23 0a 23 20 53 63 72 61 74 63  IES)..#.# Scratc
14da0 68 20 6f 6e 6c 79 2e 20 49 74 20 63 6f 70 69 65  h only. It copie
14db0 73 20 74 68 65 20 73 74 61 67 65 64 20 70 72 6f  s the staged pro
14dc0 67 72 61 6d 20 28 6e 65 76 65 72 20 72 75 6e 73  gram (never runs
14dd0 20 69 74 20 69 6e 20 70 6c 61 63 65 2c 20 73 69   it in place, si
14de0 6e 63 65 0a 23 20 61 20 70 72 6f 67 72 61 6d 20  nce.# a program 
14df0 72 75 6e 20 66 72 6f 6d 20 73 74 61 67 65 64 2f  run from staged/
14e00 6e 65 78 74 20 74 61 6b 65 73 20 74 68 61 74 20  next takes that 
14e10 74 72 65 65 27 73 20 72 6f 6f 74 20 61 73 20 69  tree's root as i
14e20 74 73 20 72 65 6c 65 61 73 65 20 72 6f 6f 74 29  ts release root)
14e30 0a 23 20 69 6e 74 6f 20 44 49 52 2f 72 6f 6f 74  .# into DIR/root
14e40 2c 20 6c 61 69 64 20 6f 75 74 20 61 73 20 73 63  , laid out as sc
14e50 72 69 70 74 73 2f 73 74 61 72 74 2d 66 6f 73 73  ripts/start-foss
14e60 69 6c 2e 63 72 20 6c 61 79 73 20 6f 75 74 20 61  il.cr lays out a
14e70 20 72 65 6c 65 61 73 65 20 72 6f 6f 74 3a 0a 23   release root:.#
14e80 20 20 20 44 49 52 2f 72 6f 6f 74 2f 63 75 72 72     DIR/root/curr
14e90 65 6e 74 2f 6f 63 78 32 2c 20 44 49 52 2f 72 6f  ent/ocx2, DIR/ro
14ea0 6f 74 2f 73 74 61 67 65 64 2f 6e 65 78 74 2f 6f  ot/staged/next/o
14eb0 63 78 32 20 20 28 63 6f 70 69 65 73 2c 20 73 61  cx2  (copies, sa
14ec0 6d 65 20 68 61 73 68 29 0a 23 20 20 20 44 49 52  me hash).#   DIR
14ed0 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69 20 20 20  /ext/ocx2-cgi   
14ee0 20 20 20 20 2d 3e 20 44 49 52 2f 72 6f 6f 74 2f      -> DIR/root/
14ef0 63 75 72 72 65 6e 74 2f 6f 63 78 32 0a 23 20 20  current/ocx2.#  
14f00 20 44 49 52 2f 65 78 74 2f 6f 63 78 32 2d 63 67   DIR/ext/ocx2-cg
14f10 69 2d 6e 65 78 74 20 20 2d 3e 20 44 49 52 2f 72  i-next  -> DIR/r
14f20 6f 6f 74 2f 73 74 61 67 65 64 2f 6e 65 78 74 2f  oot/staged/next/
14f30 6f 63 78 32 0a 23 20 20 20 44 49 52 2f 65 78 74  ocx2.#   DIR/ext
14f40 2f 77 68 6f 20 20 20 20 20 20 20 20 20 20 20 20  /who            
14f50 74 68 65 20 76 69 65 77 65 72 2d 6e 61 6d 69 6e  the viewer-namin
14f60 67 20 73 63 72 69 70 74 20 73 65 72 76 65 64 5f  g script served_
14f70 6e 6f 64 65 2e 63 72 20 77 72 69 74 65 73 0a 23  node.cr writes.#
14f80 20 45 76 65 72 79 74 68 69 6e 67 20 72 75 6e 73   Everything runs
14f90 20 77 69 74 68 20 48 4f 4d 45 3d 44 49 52 2f 68   with HOME=DIR/h
14fa0 6f 6d 65 2c 20 73 6f 20 6e 6f 20 7e 2f 2e 66 6f  ome, so no ~/.fo
14fb0 73 73 69 6c 20 6f 75 74 73 69 64 65 20 44 49 52  ssil outside DIR
14fc0 20 69 73 20 74 6f 75 63 68 65 64 2e 0a 23 0a 23   is touched..#.#
14fd0 20 57 68 61 74 20 69 74 20 6c 65 61 76 65 73 3a   What it leaves:
14fe0 0a 23 20 20 20 44 49 52 2f 73 65 72 76 65 72 2f  .#   DIR/server/
14ff0 72 65 70 6f 2e 66 6f 73 73 69 6c 20 20 20 74 68  repo.fossil   th
15000 65 20 73 65 72 76 65 64 20 72 65 70 6f 73 69 74  e served reposit
15010 6f 72 79 20 28 22 66 6f 73 73 69 6c 20 6e 65 77  ory ("fossil new
15020 20 2d 41 20 6f 77 6e 65 72 22 29 0a 23 20 20 20   -A owner").#   
15030 44 49 52 2f 73 65 72 76 65 72 2f 63 68 65 63 6b  DIR/server/check
15040 6f 75 74 20 20 20 20 20 20 61 20 63 68 65 63 6b  out      a check
15050 6f 75 74 20 6f 66 20 69 74 2c 20 74 68 65 20 73  out of it, the s
15060 65 72 76 65 72 2d 73 69 64 65 20 6f 6e 65 0a 23  erver-side one.#
15070 20 20 20 44 49 52 2f 63 6c 6f 6e 65 73 2f 69 76     DIR/clones/iv
15080 79 2f 63 6c 6f 6e 65 2e 66 6f 73 73 69 6c 2c 20  y/clone.fossil, 
15090 44 49 52 2f 63 6c 6f 6e 65 73 2f 69 76 79 2f 74  DIR/clones/ivy/t
150a0 72 65 65 0a 23 20 20 20 20 20 20 20 20 20 20 20  ree.#           
150b0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
150c0 20 61 20 63 6c 6f 6e 65 20 6d 61 64 65 20 6f 76   a clone made ov
150d0 65 72 20 48 54 54 50 20 61 73 20 69 76 79 20 28  er HTTP as ivy (
150e0 69 2c 6f 29 2c 20 69 74 73 20 70 61 73 73 77 6f  i,o), its passwo
150f0 72 64 0a 23 20 20 20 20 20 20 20 20 20 20 20 20  rd.#            
15100 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                  
15110 73 61 76 65 64 2c 20 61 75 74 6f 73 79 6e 63 20  saved, autosync 
15120 6f 66 66 2c 20 61 6e 64 20 69 74 73 20 63 68 65  off, and its che
15130 63 6b 6f 75 74 0a 23 20 20 20 44 49 52 2f 70 61  ckout.#   DIR/pa
15140 73 73 77 6f 72 64 73 2e 74 78 74 20 20 20 20 20  sswords.txt     
15150 20 20 20 22 75 73 65 72 20 70 61 73 73 77 6f 72     "user passwor
15160 64 20 63 61 70 61 62 69 6c 69 74 69 65 73 22 20  d capabilities" 
15170 70 65 72 20 6c 69 6e 65 20 28 73 63 72 61 74 63  per line (scratc
15180 68 29 0a 23 20 20 20 44 49 52 2f 66 61 63 74 73  h).#   DIR/facts
15190 2e 74 78 74 20 20 20 20 20 20 20 20 20 20 20 20  .txt            
151a0 68 61 73 68 65 73 20 6d 61 64 65 20 68 65 72 65  hashes made here
151b0 20 28 63 68 65 63 6b 2d 69 6e 73 2c 20 70 6f 73   (check-ins, pos
151c0 74 73 2c 20 74 69 63 6b 65 74 2c 20 77 69 6b 69  ts, ticket, wiki
151d0 29 0a 23 20 20 20 44 49 52 2f 65 6e 76 2e 73 68  ).#   DIR/env.sh
151e0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 22                 "
151f0 2e 20 44 49 52 2f 65 6e 76 2e 73 68 22 20 73 65  . DIR/env.sh" se
15200 74 73 20 48 4f 4d 45 2c 20 50 41 54 48 20 28 6f  ts HOME, PATH (o
15210 63 78 32 20 66 69 72 73 74 29 2c 20 55 52 4c 0a  cx2 first), URL.
15220 23 20 20 20 44 49 52 2f 73 74 61 72 74 2e 73 68  #   DIR/start.sh
15230 2c 20 44 49 52 2f 73 74 6f 70 2e 73 68 2c 20 44  , DIR/stop.sh, D
15240 49 52 2f 73 65 72 76 65 72 2e 70 69 64 2c 20 44  IR/server.pid, D
15250 49 52 2f 73 65 72 76 65 72 2e 6c 6f 67 2c 20 44  IR/server.log, D
15260 49 52 2f 73 65 72 76 65 72 2e 65 72 72 2e 6c 6f  IR/server.err.lo
15270 67 0a 23 20 54 68 65 20 73 65 72 76 65 72 20 6b  g.# The server k
15280 65 65 70 73 20 72 75 6e 6e 69 6e 67 20 77 68 65  eeps running whe
15290 6e 20 74 68 69 73 20 73 63 72 69 70 74 20 65 78  n this script ex
152a0 69 74 73 3b 20 73 74 6f 70 20 69 74 20 77 69 74  its; stop it wit
152b0 68 20 44 49 52 2f 73 74 6f 70 2e 73 68 2c 0a 23  h DIR/stop.sh,.#
152c0 20 73 74 61 72 74 20 69 74 20 61 67 61 69 6e 20   start it again 
152d0 6f 6e 20 74 68 65 20 73 61 6d 65 20 70 6f 72 74  on the same port
152e0 20 77 69 74 68 20 44 49 52 2f 73 74 61 72 74 2e   with DIR/start.
152f0 73 68 2e 20 2f 65 78 74 2f 77 68 6f 20 61 6e 73  sh. /ext/who ans
15300 77 65 72 73 0a 23 20 22 76 69 65 77 65 72 3d 55  wers.# "viewer=U
15310 53 45 52 20 63 61 70 61 62 69 6c 69 74 69 65 73  SER capabilities
15320 3d 43 41 50 53 22 20 28 69 6e 73 69 64 65 20 46  =CAPS" (inside F
15330 6f 73 73 69 6c 27 73 20 73 6b 69 6e 29 20 66 6f  ossil's skin) fo
15340 72 20 77 68 6f 65 76 65 72 20 74 68 65 0a 23 20  r whoever the.# 
15350 72 65 71 75 65 73 74 27 73 20 63 6f 6f 6b 69 65  request's cookie
15360 20 73 69 67 6e 73 20 69 6e 3b 20 6e 6f 62 6f 64   signs in; nobod
15370 79 20 73 68 6f 77 73 20 61 73 20 61 6e 20 65 6d  y shows as an em
15380 70 74 79 20 76 69 65 77 65 72 2e 0a 73 65 74 20  pty viewer..set 
15390 2d 65 75 0a 0a 5b 20 24 23 20 2d 65 71 20 32 20  -eu..[ $# -eq 2 
153a0 5d 20 7c 7c 20 7b 20 65 63 68 6f 20 22 75 73 61  ] || { echo "usa
153b0 67 65 3a 20 24 30 20 44 49 52 20 50 4f 52 54 22  ge: $0 DIR PORT"
153c0 20 3e 26 32 3b 20 65 78 69 74 20 32 3b 20 7d 0a   >&2; exit 2; }.
153d0 44 49 52 3d 24 31 0a 50 4f 52 54 3d 24 32 0a 53  DIR=$1.PORT=$2.S
153e0 54 41 47 45 44 3d 2f 76 61 72 2f 6c 69 62 2f 6f  TAGED=/var/lib/o
153f0 63 78 2f 61 67 65 6e 74 73 2f 6f 70 75 73 2d 6f  cx/agents/opus-o
15400 63 78 32 2f 70 72 6f 6a 65 63 74 73 2f 6f 6c 6c  cx2/projects/oll
15410 61 6d 61 2f 62 32 64 65 38 62 30 63 32 63 36 37  ama/b2de8b0c2c67
15420 30 30 65 62 35 63 36 38 36 62 31 37 34 37 62 35  00eb5c686b1747b5
15430 61 61 61 31 65 32 64 32 64 30 31 33 37 30 61 63  aaa1e2d2d01370ac
15440 35 35 66 32 65 35 61 31 35 31 61 36 37 65 30 33  55f2e5a151a67e03
15450 62 34 38 61 2f 73 74 61 67 65 64 2f 6e 65 78 74  b48a/staged/next
15460 2f 6f 63 78 32 0a 4e 49 43 45 3d 22 6e 69 63 65  /ocx2.NICE="nice
15470 20 2d 6e 20 31 30 22 0a 0a 63 61 73 65 20 24 50   -n 10"..case $P
15480 4f 52 54 20 69 6e 20 27 27 7c 2a 5b 21 30 2d 39  ORT in ''|*[!0-9
15490 5d 2a 29 20 65 63 68 6f 20 22 50 4f 52 54 20 6d  ]*) echo "PORT m
154a0 75 73 74 20 62 65 20 61 20 6e 75 6d 62 65 72 22  ust be a number"
154b0 20 3e 26 32 3b 20 65 78 69 74 20 32 3b 3b 20 65   >&2; exit 2;; e
154c0 73 61 63 0a 69 66 20 5b 20 2d 65 20 22 24 44 49  sac.if [ -e "$DI
154d0 52 22 20 5d 20 26 26 20 5b 20 2d 6e 20 22 24 28  R" ] && [ -n "$(
154e0 6c 73 20 2d 41 20 22 24 44 49 52 22 20 32 3e 2f  ls -A "$DIR" 2>/
154f0 64 65 76 2f 6e 75 6c 6c 29 22 20 5d 3b 20 74 68  dev/null)" ]; th
15500 65 6e 0a 20 20 65 63 68 6f 20 22 24 44 49 52 20  en.  echo "$DIR 
15510 65 78 69 73 74 73 20 61 6e 64 20 69 73 20 6e 6f  exists and is no
15520 74 20 65 6d 70 74 79 3b 20 67 69 76 65 20 61 20  t empty; give a 
15530 66 72 65 73 68 20 64 69 72 65 63 74 6f 72 79 22  fresh directory"
15540 20 3e 26 32 3b 20 65 78 69 74 20 32 0a 66 69 0a   >&2; exit 2.fi.
15550 69 66 20 63 75 72 6c 20 2d 73 20 2d 6f 20 2f 64  if curl -s -o /d
15560 65 76 2f 6e 75 6c 6c 20 2d 2d 6d 61 78 2d 74 69  ev/null --max-ti
15570 6d 65 20 32 20 22 68 74 74 70 3a 2f 2f 31 32 37  me 2 "http://127
15580 2e 30 2e 30 2e 31 3a 24 50 4f 52 54 2f 22 3b 20  .0.0.1:$PORT/"; 
15590 74 68 65 6e 0a 20 20 65 63 68 6f 20 22 73 6f 6d  then.  echo "som
155a0 65 74 68 69 6e 67 20 61 6c 72 65 61 64 79 20 61  ething already a
155b0 6e 73 77 65 72 73 20 6f 6e 20 31 32 37 2e 30 2e  nswers on 127.0.
155c0 30 2e 31 3a 24 50 4f 52 54 22 20 3e 26 32 3b 20  0.1:$PORT" >&2; 
155d0 65 78 69 74 20 32 0a 66 69 0a 0a 6d 6b 64 69 72  exit 2.fi..mkdir
155e0 20 2d 70 20 22 24 44 49 52 22 0a 44 49 52 3d 24   -p "$DIR".DIR=$
155f0 28 63 64 20 22 24 44 49 52 22 20 26 26 20 70 77  (cd "$DIR" && pw
15600 64 29 0a 55 52 4c 3d 22 68 74 74 70 3a 2f 2f 31  d).URL="http://1
15610 32 37 2e 30 2e 30 2e 31 3a 24 50 4f 52 54 22 0a  27.0.0.1:$PORT".
15620 65 78 70 6f 72 74 20 48 4f 4d 45 3d 22 24 44 49  export HOME="$DI
15630 52 2f 68 6f 6d 65 22 0a 6d 6b 64 69 72 20 2d 70  R/home".mkdir -p
15640 20 22 24 48 4f 4d 45 22 20 22 24 44 49 52 2f 73   "$HOME" "$DIR/s
15650 65 72 76 65 72 2f 63 68 65 63 6b 6f 75 74 22 20  erver/checkout" 
15660 22 24 44 49 52 2f 63 6c 6f 6e 65 73 22 20 22 24  "$DIR/clones" "$
15670 44 49 52 2f 65 78 74 22 20 5c 0a 20 20 22 24 44  DIR/ext" \.  "$D
15680 49 52 2f 72 6f 6f 74 2f 63 75 72 72 65 6e 74 22  IR/root/current"
15690 20 22 24 44 49 52 2f 72 6f 6f 74 2f 73 74 61 67   "$DIR/root/stag
156a0 65 64 2f 6e 65 78 74 22 20 22 24 44 49 52 2f 62  ed/next" "$DIR/b
156b0 69 6e 22 0a 0a 66 6f 73 73 69 6c 28 29 20 7b 20  in"..fossil() { 
156c0 24 4e 49 43 45 20 2f 75 73 72 2f 62 69 6e 2f 66  $NICE /usr/bin/f
156d0 6f 73 73 69 6c 20 22 24 40 22 3b 20 7d 0a 70 77  ossil "$@"; }.pw
156e0 28 29 20 7b 20 6f 64 20 2d 41 6e 20 2d 74 78 31  () { od -An -tx1
156f0 20 2d 4e 39 20 2f 64 65 76 2f 75 72 61 6e 64 6f   -N9 /dev/urando
15700 6d 20 7c 20 74 72 20 2d 64 20 27 20 5c 6e 27 3b  m | tr -d ' \n';
15710 20 7d 0a 0a 23 20 2d 2d 2d 20 74 68 65 20 70 72   }..# --- the pr
15720 6f 67 72 61 6d 3a 20 63 6f 70 69 65 73 20 6f 66  ogram: copies of
15730 20 74 68 65 20 73 74 61 67 65 64 20 72 65 6c 65   the staged rele
15740 61 73 65 2c 20 69 6e 20 61 20 73 63 72 61 74 63  ase, in a scratc
15750 68 20 72 65 6c 65 61 73 65 20 72 6f 6f 74 0a 63  h release root.c
15760 70 20 22 24 53 54 41 47 45 44 22 20 22 24 44 49  p "$STAGED" "$DI
15770 52 2f 72 6f 6f 74 2f 63 75 72 72 65 6e 74 2f 6f  R/root/current/o
15780 63 78 32 22 0a 63 70 20 22 24 53 54 41 47 45 44  cx2".cp "$STAGED
15790 22 20 22 24 44 49 52 2f 72 6f 6f 74 2f 73 74 61  " "$DIR/root/sta
157a0 67 65 64 2f 6e 65 78 74 2f 6f 63 78 32 22 0a 63  ged/next/ocx2".c
157b0 68 6d 6f 64 20 37 35 35 20 22 24 44 49 52 2f 72  hmod 755 "$DIR/r
157c0 6f 6f 74 2f 63 75 72 72 65 6e 74 2f 6f 63 78 32  oot/current/ocx2
157d0 22 20 22 24 44 49 52 2f 72 6f 6f 74 2f 73 74 61  " "$DIR/root/sta
157e0 67 65 64 2f 6e 65 78 74 2f 6f 63 78 32 22 0a 6c  ged/next/ocx2".l
157f0 6e 20 2d 73 20 22 24 44 49 52 2f 72 6f 6f 74 2f  n -s "$DIR/root/
15800 63 75 72 72 65 6e 74 2f 6f 63 78 32 22 20 22 24  current/ocx2" "$
15810 44 49 52 2f 65 78 74 2f 6f 63 78 32 2d 63 67 69  DIR/ext/ocx2-cgi
15820 22 0a 6c 6e 20 2d 73 20 22 24 44 49 52 2f 72 6f  ".ln -s "$DIR/ro
15830 6f 74 2f 73 74 61 67 65 64 2f 6e 65 78 74 2f 6f  ot/staged/next/o
15840 63 78 32 22 20 22 24 44 49 52 2f 65 78 74 2f 6f  cx2" "$DIR/ext/o
15850 63 78 32 2d 63 67 69 2d 6e 65 78 74 22 0a 23 20  cx2-cgi-next".# 
15860 74 68 65 20 43 4c 49 2c 20 62 79 20 69 74 73 20  the CLI, by its 
15870 6f 77 6e 20 6e 61 6d 65 0a 6c 6e 20 2d 73 20 22  own name.ln -s "
15880 24 44 49 52 2f 72 6f 6f 74 2f 63 75 72 72 65 6e  $DIR/root/curren
15890 74 2f 6f 63 78 32 22 20 22 24 44 49 52 2f 62 69  t/ocx2" "$DIR/bi
158a0 6e 2f 6f 63 78 32 22 0a 23 20 73 65 72 76 65 64  n/ocx2".# served
158b0 5f 6e 6f 64 65 2e 63 72 27 73 20 76 69 65 77 65  _node.cr's viewe
158c0 72 2d 6e 61 6d 69 6e 67 20 73 63 72 69 70 74 2c  r-naming script,
158d0 20 73 6f 20 61 20 74 65 73 74 65 72 20 63 61 6e   so a tester can
158e0 20 61 73 6b 20 46 6f 73 73 69 6c 20 77 68 6f 20   ask Fossil who 
158f0 69 74 20 73 69 67 6e 65 64 20 69 6e 0a 70 72 69  it signed in.pri
15900 6e 74 66 20 27 23 21 2f 62 69 6e 2f 73 68 5c 6e  ntf '#!/bin/sh\n
15910 70 72 69 6e 74 66 20 27 22 27 22 27 43 6f 6e 74  printf '"'"'Cont
15920 65 6e 74 2d 54 79 70 65 3a 20 74 65 78 74 2f 70  ent-Type: text/p
15930 6c 61 69 6e 5c 5c 72 5c 5c 6e 5c 5c 72 5c 5c 6e  lain\\r\\n\\r\\n
15940 76 69 65 77 65 72 3d 25 25 73 20 63 61 70 61 62  viewer=%%s capab
15950 69 6c 69 74 69 65 73 3d 25 25 73 5c 5c 6e 27 22  ilities=%%s\\n'"
15960 27 22 27 20 22 24 46 4f 53 53 49 4c 5f 55 53 45  '"' "$FOSSIL_USE
15970 52 22 20 22 24 46 4f 53 53 49 4c 5f 43 41 50 41  R" "$FOSSIL_CAPA
15980 42 49 4c 49 54 49 45 53 22 5c 6e 27 20 3e 20 22  BILITIES"\n' > "
15990 24 44 49 52 2f 65 78 74 2f 77 68 6f 22 0a 63 68  $DIR/ext/who".ch
159a0 6d 6f 64 20 37 35 35 20 22 24 44 49 52 2f 65 78  mod 755 "$DIR/ex
159b0 74 2f 77 68 6f 22 0a 0a 23 20 2d 2d 2d 20 74 68  t/who"..# --- th
159c0 65 20 72 65 70 6f 73 69 74 6f 72 79 2c 20 69 74  e repository, it
159d0 73 20 61 64 6d 69 6e 2c 20 61 6e 64 20 69 74 73  s admin, and its
159e0 20 75 73 65 72 73 0a 52 45 50 4f 3d 22 24 44 49   users.REPO="$DI
159f0 52 2f 73 65 72 76 65 72 2f 72 65 70 6f 2e 66 6f  R/server/repo.fo
15a00 73 73 69 6c 22 0a 43 4f 3d 22 24 44 49 52 2f 73  ssil".CO="$DIR/s
15a10 65 72 76 65 72 2f 63 68 65 63 6b 6f 75 74 22 0a  erver/checkout".
15a20 63 72 65 61 74 65 64 3d 24 28 63 64 20 22 24 44  created=$(cd "$D
15a30 49 52 2f 73 65 72 76 65 72 22 20 26 26 20 66 6f  IR/server" && fo
15a40 73 73 69 6c 20 6e 65 77 20 2d 41 20 6f 77 6e 65  ssil new -A owne
15a50 72 20 22 24 52 45 50 4f 22 29 0a 4f 57 4e 45 52  r "$REPO").OWNER
15a60 5f 50 57 3d 24 28 70 72 69 6e 74 66 20 27 25 73  _PW=$(printf '%s
15a70 5c 6e 27 20 22 24 63 72 65 61 74 65 64 22 20 7c  \n' "$created" |
15a80 20 73 65 64 20 2d 6e 20 27 73 2f 2e 2a 70 61 73   sed -n 's/.*pas
15a90 73 77 6f 72 64 20 69 73 20 22 5c 28 5b 5e 22 5d  sword is "\([^"]
15aa0 2a 5c 29 22 2e 2a 2f 5c 31 2f 70 27 29 0a 5b 20  *\)".*/\1/p').[ 
15ab0 2d 6e 20 22 24 4f 57 4e 45 52 5f 50 57 22 20 5d  -n "$OWNER_PW" ]
15ac0 20 7c 7c 20 7b 20 65 63 68 6f 20 22 66 6f 73 73   || { echo "foss
15ad0 69 6c 20 6e 65 77 20 70 72 69 6e 74 65 64 20 6e  il new printed n
15ae0 6f 20 70 61 73 73 77 6f 72 64 3a 20 24 63 72 65  o password: $cre
15af0 61 74 65 64 22 20 3e 26 32 3b 20 65 78 69 74 20  ated" >&2; exit 
15b00 31 3b 20 7d 0a 28 63 64 20 22 24 43 4f 22 20 26  1; }.(cd "$CO" &
15b10 26 20 66 6f 73 73 69 6c 20 6f 70 65 6e 20 22 24  & fossil open "$
15b20 52 45 50 4f 22 20 3e 2f 64 65 76 2f 6e 75 6c 6c  REPO" >/dev/null
15b30 20 26 26 20 66 6f 73 73 69 6c 20 75 73 65 72 20   && fossil user 
15b40 64 65 66 61 75 6c 74 20 6f 77 6e 65 72 20 26 26  default owner &&
15b50 20 66 6f 73 73 69 6c 20 73 65 74 74 69 6e 67 73   fossil settings
15b60 20 61 75 74 6f 73 79 6e 63 20 6f 66 66 29 0a 0a   autosync off)..
15b70 3a 20 3e 20 22 24 44 49 52 2f 70 61 73 73 77 6f  : > "$DIR/passwo
15b80 72 64 73 2e 74 78 74 22 0a 63 68 6d 6f 64 20 36  rds.txt".chmod 6
15b90 30 30 20 22 24 44 49 52 2f 70 61 73 73 77 6f 72  00 "$DIR/passwor
15ba0 64 73 2e 74 78 74 22 0a 65 63 68 6f 20 22 23 20  ds.txt".echo "# 
15bb0 75 73 65 72 20 70 61 73 73 77 6f 72 64 20 63 61  user password ca
15bc0 70 61 62 69 6c 69 74 69 65 73 20 20 20 28 73 63  pabilities   (sc
15bd0 72 61 74 63 68 20 70 61 73 73 77 6f 72 64 73 20  ratch passwords 
15be0 66 6f 72 20 24 55 52 4c 29 22 20 3e 3e 20 22 24  for $URL)" >> "$
15bf0 44 49 52 2f 70 61 73 73 77 6f 72 64 73 2e 74 78  DIR/passwords.tx
15c00 74 22 0a 65 63 68 6f 20 22 6f 77 6e 65 72 20 24  t".echo "owner $
15c10 4f 57 4e 45 52 5f 50 57 20 73 20 20 20 28 66 6f  OWNER_PW s   (fo
15c20 73 73 69 6c 20 6e 65 77 20 2d 41 29 22 20 3e 3e  ssil new -A)" >>
15c30 20 22 24 44 49 52 2f 70 61 73 73 77 6f 72 64 73   "$DIR/passwords
15c40 2e 74 78 74 22 0a 61 64 64 5f 75 73 65 72 28 29  .txt".add_user()
15c50 20 7b 20 23 20 6c 6f 67 69 6e 20 63 61 70 73 0a   { # login caps.
15c60 20 20 70 3d 24 28 70 77 29 0a 20 20 28 63 64 20    p=$(pw).  (cd 
15c70 22 24 43 4f 22 20 26 26 20 66 6f 73 73 69 6c 20  "$CO" && fossil 
15c80 75 73 65 72 20 6e 65 77 20 22 24 31 22 20 22 24  user new "$1" "$
15c90 31 40 73 63 72 61 74 63 68 2e 69 6e 76 61 6c 69  1@scratch.invali
15ca0 64 22 20 22 24 70 22 20 3e 2f 64 65 76 2f 6e 75  d" "$p" >/dev/nu
15cb0 6c 6c 20 26 26 20 66 6f 73 73 69 6c 20 75 73 65  ll && fossil use
15cc0 72 20 63 61 70 61 62 69 6c 69 74 69 65 73 20 22  r capabilities "
15cd0 24 31 22 20 22 24 32 22 20 3e 2f 64 65 76 2f 6e  $1" "$2" >/dev/n
15ce0 75 6c 6c 29 0a 20 20 65 63 68 6f 20 22 24 31 20  ull).  echo "$1 
15cf0 24 70 20 24 32 22 20 3e 3e 20 22 24 44 49 52 2f  $p $2" >> "$DIR/
15d00 70 61 73 73 77 6f 72 64 73 2e 74 78 74 22 0a 7d  passwords.txt".}
15d10 0a 61 64 64 5f 75 73 65 72 20 73 61 6c 6c 79 20  .add_user sally 
15d20 73 20 20 20 20 20 23 20 73 65 74 75 70 0a 61 64  s     # setup.ad
15d30 64 5f 75 73 65 72 20 61 64 61 6d 20 61 20 20 20  d_user adam a   
15d40 20 20 20 23 20 61 64 6d 69 6e 0a 61 64 64 5f 75     # admin.add_u
15d50 73 65 72 20 69 76 79 20 69 6f 20 20 20 20 20 20  ser ivy io      
15d60 23 20 63 68 65 63 6b 2d 69 6e 20 61 6e 64 20 72  # check-in and r
15d70 65 61 64 0a 61 64 64 5f 75 73 65 72 20 6f 74 74  ead.add_user ott
15d80 6f 20 6f 20 20 20 20 20 20 23 20 72 65 61 64 20  o o      # read 
15d90 6f 6e 6c 79 0a 61 64 64 5f 75 73 65 72 20 72 69  only.add_user ri
15da0 74 61 20 52 69 20 20 20 20 20 23 20 4f 43 58 27  ta Ri     # OCX'
15db0 73 20 72 75 6e 20 73 65 6e 64 65 72 20 28 52 29  s run sender (R)
15dc0 20 77 69 74 68 20 63 68 65 63 6b 2d 69 6e 0a 23   with check-in.#
15dd0 20 6e 6f 62 6f 64 79 20 61 6e 64 20 61 6e 6f 6e   nobody and anon
15de0 79 6d 6f 75 73 20 6b 65 65 70 20 77 68 61 74 20  ymous keep what 
15df0 22 66 6f 73 73 69 6c 20 6e 65 77 22 20 67 69 76  "fossil new" giv
15e00 65 73 20 74 68 65 6d 0a 70 61 73 73 77 6f 72 64  es them.password
15e10 5f 6f 66 28 29 20 7b 20 61 77 6b 20 2d 76 20 75  _of() { awk -v u
15e20 3d 22 24 31 22 20 27 24 31 3d 3d 75 20 7b 70 72  ="$1" '$1==u {pr
15e30 69 6e 74 20 24 32 7d 27 20 22 24 44 49 52 2f 70  int $2}' "$DIR/p
15e40 61 73 73 77 6f 72 64 73 2e 74 78 74 22 3b 20 7d  asswords.txt"; }
15e50 0a 0a 23 20 2d 2d 2d 20 63 68 65 63 6b 2d 69 6e  ..# --- check-in
15e60 73 20 62 79 20 64 69 66 66 65 72 65 6e 74 20 75  s by different u
15e70 73 65 72 73 0a 63 6f 6d 6d 69 74 28 29 20 7b 20  sers.commit() { 
15e80 23 20 75 73 65 72 20 66 69 6c 65 20 63 6f 6e 74  # user file cont
15e90 65 6e 74 20 63 6f 6d 6d 65 6e 74 0a 20 20 28 63  ent comment.  (c
15ea0 64 20 22 24 43 4f 22 20 26 26 20 70 72 69 6e 74  d "$CO" && print
15eb0 66 20 27 25 73 5c 6e 27 20 22 24 33 22 20 3e 20  f '%s\n' "$3" > 
15ec0 22 24 32 22 20 26 26 20 66 6f 73 73 69 6c 20 61  "$2" && fossil a
15ed0 64 64 20 22 24 32 22 20 3e 2f 64 65 76 2f 6e 75  dd "$2" >/dev/nu
15ee0 6c 6c 20 26 26 20 5c 0a 20 20 20 66 6f 73 73 69  ll && \.   fossi
15ef0 6c 20 63 6f 6d 6d 69 74 20 2d 2d 6e 6f 2d 77 61  l commit --no-wa
15f00 72 6e 69 6e 67 73 20 2d 2d 75 73 65 72 20 22 24  rnings --user "$
15f10 31 22 20 2d 6d 20 22 24 34 22 20 3e 2f 64 65 76  1" -m "$4" >/dev
15f20 2f 6e 75 6c 6c 29 0a 7d 0a 63 6f 6d 6d 69 74 20  /null).}.commit 
15f30 6f 77 6e 65 72 20 52 45 41 44 4d 45 2e 6d 64 20  owner README.md 
15f40 22 23 20 73 63 72 61 74 63 68 20 70 72 6f 6a 65  "# scratch proje
15f50 63 74 22 20 22 53 74 61 72 74 20 74 68 65 20 73  ct" "Start the s
15f60 63 72 61 74 63 68 20 70 72 6f 6a 65 63 74 2e 22  cratch project."
15f70 0a 63 6f 6d 6d 69 74 20 69 76 79 20 68 65 6c 6c  .commit ivy hell
15f80 6f 2e 74 78 74 20 22 68 65 6c 6c 6f 22 20 22 41  o.txt "hello" "A
15f90 64 64 20 68 65 6c 6c 6f 2e 22 0a 63 6f 6d 6d 69  dd hello.".commi
15fa0 74 20 73 61 6c 6c 79 20 50 4c 41 4e 2e 6d 64 20  t sally PLAN.md 
15fb0 22 50 6c 61 6e 3a 20 6e 6f 74 68 69 6e 67 20 79  "Plan: nothing y
15fc0 65 74 2e 22 20 22 41 64 64 20 61 20 70 6c 61 6e  et." "Add a plan
15fd0 2e 22 0a 63 6f 6d 6d 69 74 20 69 76 79 20 68 65  .".commit ivy he
15fe0 6c 6c 6f 2e 74 78 74 20 22 68 65 6c 6c 6f 2c 20  llo.txt "hello, 
15ff0 77 6f 72 6c 64 22 20 22 53 61 79 20 6d 6f 72 65  world" "Say more
16000 20 69 6e 20 68 65 6c 6c 6f 2e 22 0a 63 68 65 63   in hello.".chec
16010 6b 69 6e 73 3d 24 28 66 6f 73 73 69 6c 20 73 71  kins=$(fossil sq
16020 6c 20 2d 52 20 22 24 52 45 50 4f 22 20 22 53 45  l -R "$REPO" "SE
16030 4c 45 43 54 20 62 2e 75 75 69 64 7c 7c 27 20 27  LECT b.uuid||' '
16040 7c 7c 65 2e 75 73 65 72 20 46 52 4f 4d 20 65 76  ||e.user FROM ev
16050 65 6e 74 20 65 20 4a 4f 49 4e 20 62 6c 6f 62 20  ent e JOIN blob 
16060 62 20 4f 4e 20 62 2e 72 69 64 3d 65 2e 6f 62 6a  b ON b.rid=e.obj
16070 69 64 20 57 48 45 52 45 20 65 2e 74 79 70 65 3d  id WHERE e.type=
16080 27 63 69 27 20 4f 52 44 45 52 20 42 59 20 65 2e  'ci' ORDER BY e.
16090 6d 74 69 6d 65 22 29 0a 0a 23 20 2d 2d 2d 20 61  mtime")..# --- a
160a0 20 77 69 6b 69 20 70 61 67 65 2c 20 62 79 20 61   wiki page, by a
160b0 64 61 6d 0a 28 63 64 20 22 24 43 4f 22 20 26 26  dam.(cd "$CO" &&
160c0 20 66 6f 73 73 69 6c 20 75 73 65 72 20 64 65 66   fossil user def
160d0 61 75 6c 74 20 61 64 61 6d 20 26 26 20 70 72 69  ault adam && pri
160e0 6e 74 66 20 27 23 20 4e 6f 74 65 73 5c 6e 5c 6e  ntf '# Notes\n\n
160f0 53 63 72 61 74 63 68 20 6e 6f 74 65 73 20 66 6f  Scratch notes fo
16100 72 20 74 65 73 74 65 72 73 2e 5c 6e 27 20 3e 20  r testers.\n' > 
16110 22 24 44 49 52 2f 73 65 72 76 65 72 2f 6e 6f 74  "$DIR/server/not
16120 65 73 2e 6d 64 22 20 26 26 20 5c 0a 20 66 6f 73  es.md" && \. fos
16130 73 69 6c 20 77 69 6b 69 20 63 72 65 61 74 65 20  sil wiki create 
16140 4e 6f 74 65 73 20 22 24 44 49 52 2f 73 65 72 76  Notes "$DIR/serv
16150 65 72 2f 6e 6f 74 65 73 2e 6d 64 22 20 2d 2d 6d  er/notes.md" --m
16160 69 6d 65 74 79 70 65 20 74 65 78 74 2f 78 2d 6d  imetype text/x-m
16170 61 72 6b 64 6f 77 6e 20 3e 2f 64 65 76 2f 6e 75  arkdown >/dev/nu
16180 6c 6c 29 0a 0a 23 20 2d 2d 2d 20 61 20 74 69 63  ll)..# --- a tic
16190 6b 65 74 20 61 6e 64 20 69 74 73 20 63 68 61 6e  ket and its chan
161a0 67 65 73 2c 20 62 79 20 64 69 66 66 65 72 65 6e  ges, by differen
161b0 74 20 75 73 65 72 73 0a 28 63 64 20 22 24 43 4f  t users.(cd "$CO
161c0 22 20 26 26 20 66 6f 73 73 69 6c 20 75 73 65 72  " && fossil user
161d0 20 64 65 66 61 75 6c 74 20 6f 77 6e 65 72 29 0a   default owner).
161e0 74 6b 74 5f 6f 75 74 3d 24 28 63 64 20 22 24 43  tkt_out=$(cd "$C
161f0 4f 22 20 26 26 20 66 6f 73 73 69 6c 20 74 69 63  O" && fossil tic
16200 6b 65 74 20 61 64 64 20 74 69 74 6c 65 20 22 53  ket add title "S
16210 63 72 61 74 63 68 20 74 69 63 6b 65 74 22 20 73  cratch ticket" s
16220 74 61 74 75 73 20 4f 70 65 6e 20 74 79 70 65 20  tatus Open type 
16230 43 6f 64 65 5f 44 65 66 65 63 74 20 63 6f 6d 6d  Code_Defect comm
16240 65 6e 74 20 22 46 69 72 73 74 20 72 65 70 6f 72  ent "First repor
16250 74 2e 22 29 0a 54 49 43 4b 45 54 3d 24 28 70 72  t.").TICKET=$(pr
16260 69 6e 74 66 20 27 25 73 5c 6e 27 20 22 24 74 6b  intf '%s\n' "$tk
16270 74 5f 6f 75 74 22 20 7c 20 73 65 64 20 2d 6e 20  t_out" | sed -n 
16280 27 73 2f 2e 2a 66 6f 72 20 5c 28 5b 30 2d 39 61  's/.*for \([0-9a
16290 2d 66 5d 5c 7b 34 30 2c 36 34 5c 7d 5c 29 2e 2a  -f]\{40,64\}\).*
162a0 2f 5c 31 2f 70 27 29 0a 5b 20 2d 6e 20 22 24 54  /\1/p').[ -n "$T
162b0 49 43 4b 45 54 22 20 5d 20 7c 7c 20 7b 20 65 63  ICKET" ] || { ec
162c0 68 6f 20 22 74 69 63 6b 65 74 20 61 64 64 20 70  ho "ticket add p
162d0 72 69 6e 74 65 64 20 6e 6f 20 68 61 73 68 3a 20  rinted no hash: 
162e0 24 74 6b 74 5f 6f 75 74 22 20 3e 26 32 3b 20 65  $tkt_out" >&2; e
162f0 78 69 74 20 31 3b 20 7d 0a 28 63 64 20 22 24 43  xit 1; }.(cd "$C
16300 4f 22 20 26 26 20 66 6f 73 73 69 6c 20 75 73 65  O" && fossil use
16310 72 20 64 65 66 61 75 6c 74 20 69 76 79 20 26 26  r default ivy &&
16320 20 66 6f 73 73 69 6c 20 74 69 63 6b 65 74 20 63   fossil ticket c
16330 68 61 6e 67 65 20 22 24 54 49 43 4b 45 54 22 20  hange "$TICKET" 
16340 69 63 6f 6d 6d 65 6e 74 20 22 53 65 65 6e 20 69  icomment "Seen i
16350 74 20 74 6f 6f 2c 20 62 79 20 69 76 79 2e 22 20  t too, by ivy." 
16360 3e 2f 64 65 76 2f 6e 75 6c 6c 29 0a 28 63 64 20  >/dev/null).(cd 
16370 22 24 43 4f 22 20 26 26 20 66 6f 73 73 69 6c 20  "$CO" && fossil 
16380 75 73 65 72 20 64 65 66 61 75 6c 74 20 73 61 6c  user default sal
16390 6c 79 20 26 26 20 66 6f 73 73 69 6c 20 74 69 63  ly && fossil tic
163a0 6b 65 74 20 63 68 61 6e 67 65 20 22 24 54 49 43  ket change "$TIC
163b0 4b 45 54 22 20 73 74 61 74 75 73 20 46 69 78 65  KET" status Fixe
163c0 64 20 69 63 6f 6d 6d 65 6e 74 20 22 46 69 78 65  d icomment "Fixe
163d0 64 2c 20 62 79 20 73 61 6c 6c 79 2e 22 20 3e 2f  d, by sally." >/
163e0 64 65 76 2f 6e 75 6c 6c 29 0a 28 63 64 20 22 24  dev/null).(cd "$
163f0 43 4f 22 20 26 26 20 66 6f 73 73 69 6c 20 75 73  CO" && fossil us
16400 65 72 20 64 65 66 61 75 6c 74 20 6f 77 6e 65 72  er default owner
16410 29 0a 0a 23 20 2d 2d 2d 20 74 68 65 20 73 65 72  )..# --- the ser
16420 76 65 72 0a 65 63 68 6f 20 22 24 50 4f 52 54 22  ver.echo "$PORT"
16430 20 3e 20 22 24 44 49 52 2f 73 65 72 76 65 72 2e   > "$DIR/server.
16440 70 6f 72 74 22 0a 63 64 20 22 24 44 49 52 22 0a  port".cd "$DIR".
16450 63 61 74 20 3e 20 22 24 44 49 52 2f 73 74 61 72  cat > "$DIR/star
16460 74 2e 73 68 22 20 3c 3c 45 4f 46 0a 23 21 2f 62  t.sh" <<EOF.#!/b
16470 69 6e 2f 73 68 0a 23 20 53 74 61 72 74 73 20 28  in/sh.# Starts (
16480 61 67 61 69 6e 29 20 74 68 65 20 73 63 72 61 74  again) the scrat
16490 63 68 20 73 65 72 76 65 72 20 66 6f 72 20 24 44  ch server for $D
164a0 49 52 20 6f 6e 20 31 32 37 2e 30 2e 30 2e 31 3a  IR on 127.0.0.1:
164b0 24 50 4f 52 54 2c 20 6e 69 63 65 64 2c 20 69 6e  $PORT, niced, in
164c0 0a 23 20 69 74 73 20 6f 77 6e 20 73 65 73 73 69  .# its own sessi
164d0 6f 6e 3b 20 44 49 52 2f 73 74 6f 70 2e 73 68 20  on; DIR/stop.sh 
164e0 73 74 6f 70 73 20 69 74 2e 0a 5b 20 2d 66 20 22  stops it..[ -f "
164f0 24 44 49 52 2f 73 65 72 76 65 72 2e 70 69 64 22  $DIR/server.pid"
16500 20 5d 20 26 26 20 6b 69 6c 6c 20 2d 30 20 22 5c   ] && kill -0 "\
16510 24 28 63 61 74 20 22 24 44 49 52 2f 73 65 72 76  $(cat "$DIR/serv
16520 65 72 2e 70 69 64 22 29 22 20 32 3e 2f 64 65 76  er.pid")" 2>/dev
16530 2f 6e 75 6c 6c 20 26 26 20 7b 20 65 63 68 6f 20  /null && { echo 
16540 22 61 6c 72 65 61 64 79 20 72 75 6e 6e 69 6e 67  "already running
16550 22 20 3e 26 32 3b 20 65 78 69 74 20 31 3b 20 7d  " >&2; exit 1; }
16560 0a 63 64 20 22 24 44 49 52 22 0a 48 4f 4d 45 3d  .cd "$DIR".HOME=
16570 22 24 44 49 52 2f 68 6f 6d 65 22 20 73 65 74 73  "$DIR/home" sets
16580 69 64 20 6e 69 63 65 20 2d 6e 20 31 30 20 2f 75  id nice -n 10 /u
16590 73 72 2f 62 69 6e 2f 66 6f 73 73 69 6c 20 73 65  sr/bin/fossil se
165a0 72 76 65 72 20 2d 2d 6c 6f 63 61 6c 68 6f 73 74  rver --localhost
165b0 20 2d 2d 70 6f 72 74 20 22 24 50 4f 52 54 22 20   --port "$PORT" 
165c0 2d 2d 6e 6f 6a 61 69 6c 20 5c 5c 0a 20 20 2d 2d  --nojail \\.  --
165d0 65 78 74 72 6f 6f 74 20 22 24 44 49 52 2f 65 78  extroot "$DIR/ex
165e0 74 22 20 2d 2d 65 72 72 6f 72 6c 6f 67 20 22 24  t" --errorlog "$
165f0 44 49 52 2f 73 65 72 76 65 72 2e 65 72 72 2e 6c  DIR/server.err.l
16600 6f 67 22 20 22 24 52 45 50 4f 22 20 3e 3e 20 22  og" "$REPO" >> "
16610 24 44 49 52 2f 73 65 72 76 65 72 2e 6c 6f 67 22  $DIR/server.log"
16620 20 32 3e 26 31 20 3c 20 2f 64 65 76 2f 6e 75 6c   2>&1 < /dev/nul
16630 6c 20 26 0a 65 63 68 6f 20 5c 24 21 20 3e 20 22  l &.echo \$! > "
16640 24 44 49 52 2f 73 65 72 76 65 72 2e 70 69 64 22  $DIR/server.pid"
16650 0a 69 3d 30 0a 75 6e 74 69 6c 20 63 75 72 6c 20  .i=0.until curl 
16660 2d 73 20 2d 6f 20 2f 64 65 76 2f 6e 75 6c 6c 20  -s -o /dev/null 
16670 2d 2d 6d 61 78 2d 74 69 6d 65 20 31 20 22 24 55  --max-time 1 "$U
16680 52 4c 2f 22 3b 20 64 6f 0a 20 20 69 3d 5c 24 28  RL/"; do.  i=\$(
16690 28 69 2b 31 29 29 3b 20 5b 20 5c 24 69 20 2d 6c  (i+1)); [ \$i -l
166a0 74 20 35 30 20 5d 20 7c 7c 20 7b 20 65 63 68 6f  t 50 ] || { echo
166b0 20 22 66 6f 73 73 69 6c 20 73 65 72 76 65 72 20   "fossil server 
166c0 64 69 64 20 6e 6f 74 20 61 6e 73 77 65 72 20 6f  did not answer o
166d0 6e 20 24 55 52 4c 22 20 3e 26 32 3b 20 22 24 44  n $URL" >&2; "$D
166e0 49 52 2f 73 74 6f 70 2e 73 68 22 3b 20 65 78 69  IR/stop.sh"; exi
166f0 74 20 31 3b 20 7d 0a 20 20 73 6c 65 65 70 20 30  t 1; }.  sleep 0
16700 2e 31 0a 64 6f 6e 65 0a 65 63 68 6f 20 22 73 65  .1.done.echo "se
16710 72 76 69 6e 67 20 24 55 52 4c 20 28 70 69 64 20  rving $URL (pid 
16720 5c 24 28 63 61 74 20 22 24 44 49 52 2f 73 65 72  \$(cat "$DIR/ser
16730 76 65 72 2e 70 69 64 22 29 29 22 0a 45 4f 46 0a  ver.pid"))".EOF.
16740 63 68 6d 6f 64 20 37 35 35 20 22 24 44 49 52 2f  chmod 755 "$DIR/
16750 73 74 61 72 74 2e 73 68 22 0a 63 61 74 20 3e 20  start.sh".cat > 
16760 22 24 44 49 52 2f 73 74 6f 70 2e 73 68 22 20 3c  "$DIR/stop.sh" <
16770 3c 45 4f 46 0a 23 21 2f 62 69 6e 2f 73 68 0a 23  <EOF.#!/bin/sh.#
16780 20 53 74 6f 70 73 20 74 68 65 20 73 63 72 61 74   Stops the scrat
16790 63 68 20 73 65 72 76 65 72 20 73 65 74 75 70 2e  ch server setup.
167a0 73 68 20 73 74 61 72 74 65 64 20 66 6f 72 20 24  sh started for $
167b0 44 49 52 3a 20 69 74 73 20 70 72 6f 63 65 73 73  DIR: its process
167c0 20 67 72 6f 75 70 2c 0a 23 20 61 6e 64 20 61 6e   group,.# and an
167d0 79 20 70 72 6f 63 65 73 73 20 73 74 69 6c 6c 20  y process still 
167e0 73 65 72 76 69 6e 67 20 74 68 69 73 20 72 65 70  serving this rep
167f0 6f 73 69 74 6f 72 79 2c 20 73 75 63 68 20 61 73  ository, such as
16800 20 46 6f 73 73 69 6c 27 73 0a 23 20 62 61 63 6b   Fossil's.# back
16810 6f 66 66 69 63 65 2c 20 77 68 69 63 68 20 6c 65  office, which le
16820 61 76 65 73 20 69 74 73 20 73 65 72 76 65 72 27  aves its server'
16830 73 20 70 72 6f 63 65 73 73 20 67 72 6f 75 70 20  s process group 
16840 61 6e 64 20 6d 61 79 20 6c 69 6e 67 65 72 2e 0a  and may linger..
16850 70 69 64 3d 5c 24 28 63 61 74 20 22 24 44 49 52  pid=\$(cat "$DIR
16860 2f 73 65 72 76 65 72 2e 70 69 64 22 20 32 3e 2f  /server.pid" 2>/
16870 64 65 76 2f 6e 75 6c 6c 29 0a 5b 20 2d 6e 20 22  dev/null).[ -n "
16880 5c 24 70 69 64 22 20 5d 20 26 26 20 7b 20 6b 69  \$pid" ] && { ki
16890 6c 6c 20 2d 54 45 52 4d 20 2d 2d 20 2d 5c 24 70  ll -TERM -- -\$p
168a0 69 64 20 32 3e 2f 64 65 76 2f 6e 75 6c 6c 20 7c  id 2>/dev/null |
168b0 7c 20 6b 69 6c 6c 20 2d 54 45 52 4d 20 5c 24 70  | kill -TERM \$p
168c0 69 64 20 32 3e 2f 64 65 76 2f 6e 75 6c 6c 3b 20  id 2>/dev/null; 
168d0 7d 0a 73 65 72 76 69 6e 67 28 29 20 7b 0a 20 20  }.serving() {.  
168e0 66 6f 72 20 70 20 69 6e 20 2f 70 72 6f 63 2f 5b  for p in /proc/[
168f0 30 2d 39 5d 2a 3b 20 64 6f 0a 20 20 20 20 63 3d  0-9]*; do.    c=
16900 5c 24 28 74 72 20 27 5c 5c 30 27 20 27 20 27 20  \$(tr '\\0' ' ' 
16910 32 3e 2f 64 65 76 2f 6e 75 6c 6c 20 3c 20 5c 24  2>/dev/null < \$
16920 70 2f 63 6d 64 6c 69 6e 65 29 20 7c 7c 20 63 6f  p/cmdline) || co
16930 6e 74 69 6e 75 65 0a 20 20 20 20 63 61 73 65 20  ntinue.    case 
16940 22 5c 24 63 22 20 69 6e 20 2a 22 66 6f 73 73 69  "\$c" in *"fossi
16950 6c 20 73 65 72 76 65 72 20 22 2a 22 24 52 45 50  l server "*"$REP
16960 4f 22 2a 29 20 65 63 68 6f 20 5c 24 7b 70 23 2f  O"*) echo \${p#/
16970 70 72 6f 63 2f 7d 3b 3b 20 65 73 61 63 0a 20 20  proc/};; esac.  
16980 64 6f 6e 65 0a 7d 0a 66 6f 72 20 69 20 69 6e 20  done.}.for i in 
16990 31 20 32 20 33 20 34 20 35 20 36 20 37 20 38 20  1 2 3 4 5 6 7 8 
169a0 39 20 31 30 3b 20 64 6f 0a 20 20 6c 65 66 74 3d  9 10; do.  left=
169b0 5c 24 28 73 65 72 76 69 6e 67 29 3b 20 5b 20 2d  \$(serving); [ -
169c0 7a 20 22 5c 24 6c 65 66 74 22 20 5d 20 26 26 20  z "\$left" ] && 
169d0 62 72 65 61 6b 0a 20 20 6b 69 6c 6c 20 2d 54 45  break.  kill -TE
169e0 52 4d 20 5c 24 6c 65 66 74 20 32 3e 2f 64 65 76  RM \$left 2>/dev
169f0 2f 6e 75 6c 6c 3b 20 73 6c 65 65 70 20 30 2e 32  /null; sleep 0.2
16a00 0a 64 6f 6e 65 0a 6c 65 66 74 3d 5c 24 28 73 65  .done.left=\$(se
16a10 72 76 69 6e 67 29 3b 20 5b 20 2d 6e 20 22 5c 24  rving); [ -n "\$
16a20 6c 65 66 74 22 20 5d 20 26 26 20 6b 69 6c 6c 20  left" ] && kill 
16a30 2d 4b 49 4c 4c 20 5c 24 6c 65 66 74 20 32 3e 2f  -KILL \$left 2>/
16a40 64 65 76 2f 6e 75 6c 6c 0a 72 6d 20 2d 66 20 22  dev/null.rm -f "
16a50 24 44 49 52 2f 73 65 72 76 65 72 2e 70 69 64 22  $DIR/server.pid"
16a60 0a 5b 20 2d 7a 20 22 5c 24 28 73 65 72 76 69 6e  .[ -z "\$(servin
16a70 67 29 22 20 5d 20 26 26 20 65 63 68 6f 20 22 73  g)" ] && echo "s
16a80 74 6f 70 70 65 64 3a 20 6e 6f 74 68 69 6e 67 20  topped: nothing 
16a90 73 65 72 76 65 73 20 24 52 45 50 4f 22 20 7c 7c  serves $REPO" ||
16aa0 20 7b 20 65 63 68 6f 20 22 73 74 69 6c 6c 20 73   { echo "still s
16ab0 65 72 76 69 6e 67 3a 20 5c 24 28 73 65 72 76 69  erving: \$(servi
16ac0 6e 67 29 22 20 3e 26 32 3b 20 65 78 69 74 20 31  ng)" >&2; exit 1
16ad0 3b 20 7d 0a 45 4f 46 0a 63 68 6d 6f 64 20 37 35  ; }.EOF.chmod 75
16ae0 35 20 22 24 44 49 52 2f 73 74 6f 70 2e 73 68 22  5 "$DIR/stop.sh"
16af0 0a 23 20 61 20 66 61 69 6c 75 72 65 20 66 72 6f  .# a failure fro
16b00 6d 20 68 65 72 65 20 6f 6e 20 6c 65 61 76 65 73  m here on leaves
16b10 20 6e 6f 20 73 65 72 76 65 72 20 72 75 6e 6e 69   no server runni
16b20 6e 67 0a 74 72 61 70 20 27 73 74 3d 24 3f 3b 20  ng.trap 'st=$?; 
16b30 5b 20 24 73 74 20 2d 65 71 20 30 20 5d 20 7c 7c  [ $st -eq 0 ] ||
16b40 20 7b 20 65 63 68 6f 20 22 73 65 74 75 70 20 66   { echo "setup f
16b50 61 69 6c 65 64 20 28 24 73 74 29 3b 20 73 74 6f  ailed ($st); sto
16b60 70 70 69 6e 67 20 74 68 65 20 73 65 72 76 65 72  pping the server
16b70 22 20 3e 26 32 3b 20 22 24 44 49 52 2f 73 74 6f  " >&2; "$DIR/sto
16b80 70 2e 73 68 22 20 3e 26 32 3b 20 7d 27 20 45 58  p.sh" >&2; }' EX
16b90 49 54 0a 22 24 44 49 52 2f 73 74 61 72 74 2e 73  IT."$DIR/start.s
16ba0 68 22 20 3e 2f 64 65 76 2f 6e 75 6c 6c 0a 0a 23  h" >/dev/null..#
16bb0 20 2d 2d 2d 20 61 20 66 6f 72 75 6d 20 74 68 72   --- a forum thr
16bc0 65 61 64 20 74 68 72 6f 75 67 68 20 46 6f 73 73  ead through Foss
16bd0 69 6c 27 73 20 6f 77 6e 20 66 6f 72 6d 2c 20 72  il's own form, r
16be0 65 70 6c 69 65 73 20 62 79 20 64 69 66 66 65 72  eplies by differ
16bf0 65 6e 74 20 75 73 65 72 73 0a 4a 41 52 53 3d 22  ent users.JARS="
16c00 24 44 49 52 2f 68 6f 6d 65 2f 6a 61 72 73 22 3b  $DIR/home/jars";
16c10 20 6d 6b 64 69 72 20 2d 70 20 22 24 4a 41 52 53   mkdir -p "$JARS
16c20 22 0a 6c 6f 67 69 6e 28 29 20 7b 20 23 20 75 73  ".login() { # us
16c30 65 72 20 2d 3e 20 63 6f 6f 6b 69 65 20 6a 61 72  er -> cookie jar
16c40 20 70 61 74 68 0a 20 20 63 75 72 6c 20 2d 73 20   path.  curl -s 
16c50 2d 6f 20 2f 64 65 76 2f 6e 75 6c 6c 20 2d 63 20  -o /dev/null -c 
16c60 22 24 4a 41 52 53 2f 24 31 22 20 2d 2d 64 61 74  "$JARS/$1" --dat
16c70 61 2d 75 72 6c 65 6e 63 6f 64 65 20 22 75 3d 24  a-urlencode "u=$
16c80 31 22 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63  1" --data-urlenc
16c90 6f 64 65 20 22 70 3d 24 28 70 61 73 73 77 6f 72  ode "p=$(passwor
16ca0 64 5f 6f 66 20 22 24 31 22 29 22 20 2d 64 20 69  d_of "$1")" -d i
16cb0 6e 3d 31 20 22 24 55 52 4c 2f 6c 6f 67 69 6e 22  n=1 "$URL/login"
16cc0 0a 20 20 67 72 65 70 20 2d 71 20 66 6f 73 73 69  .  grep -q fossi
16cd0 6c 2d 20 22 24 4a 41 52 53 2f 24 31 22 20 7c 7c  l- "$JARS/$1" ||
16ce0 20 7b 20 65 63 68 6f 20 22 6c 6f 67 69 6e 20 61   { echo "login a
16cf0 73 20 24 31 20 73 65 74 20 6e 6f 20 63 6f 6f 6b  s $1 set no cook
16d00 69 65 22 20 3e 26 32 3b 20 65 78 69 74 20 31 3b  ie" >&2; exit 1;
16d10 20 7d 0a 7d 0a 63 73 72 66 28 29 20 7b 20 73 65   }.}.csrf() { se
16d20 64 20 2d 6e 20 27 73 2f 2e 2a 6e 61 6d 65 3d 22  d -n 's/.*name="
16d30 63 73 72 66 22 20 76 61 6c 75 65 3d 22 5c 28 5b  csrf" value="\([
16d40 5e 22 5d 2a 5c 29 22 2e 2a 2f 5c 31 2f 70 27 20  ^"]*\)".*/\1/p' 
16d50 7c 20 68 65 61 64 20 2d 6e 20 31 3b 20 7d 0a 6c  | head -n 1; }.l
16d60 61 74 65 73 74 5f 70 6f 73 74 28 29 20 7b 20 66  atest_post() { f
16d70 6f 73 73 69 6c 20 73 71 6c 20 2d 52 20 22 24 52  ossil sql -R "$R
16d80 45 50 4f 22 20 22 53 45 4c 45 43 54 20 62 2e 75  EPO" "SELECT b.u
16d90 75 69 64 20 46 52 4f 4d 20 62 6c 6f 62 20 62 20  uid FROM blob b 
16da0 4a 4f 49 4e 20 66 6f 72 75 6d 70 6f 73 74 20 66  JOIN forumpost f
16db0 20 4f 4e 20 62 2e 72 69 64 3d 66 2e 66 70 69 64   ON b.rid=f.fpid
16dc0 20 4f 52 44 45 52 20 42 59 20 66 2e 66 6d 74 69   ORDER BY f.fmti
16dd0 6d 65 20 44 45 53 43 2c 20 66 2e 66 70 69 64 20  me DESC, f.fpid 
16de0 44 45 53 43 20 4c 49 4d 49 54 20 31 22 20 7c 20  DESC LIMIT 1" | 
16df0 74 72 20 2d 64 20 22 27 22 3b 20 7d 0a 6e 65 77  tr -d "'"; }.new
16e00 5f 74 68 72 65 61 64 28 29 20 7b 20 23 20 75 73  _thread() { # us
16e10 65 72 20 74 69 74 6c 65 20 63 6f 6e 74 65 6e 74  er title content
16e20 0a 20 20 6c 6f 67 69 6e 20 22 24 31 22 0a 20 20  .  login "$1".  
16e30 74 3d 24 28 63 75 72 6c 20 2d 73 20 2d 62 20 22  t=$(curl -s -b "
16e40 24 4a 41 52 53 2f 24 31 22 20 22 24 55 52 4c 2f  $JARS/$1" "$URL/
16e50 66 6f 72 75 6d 6e 65 77 22 20 7c 20 63 73 72 66  forumnew" | csrf
16e60 29 0a 20 20 63 75 72 6c 20 2d 73 20 2d 6f 20 2f  ).  curl -s -o /
16e70 64 65 76 2f 6e 75 6c 6c 20 2d 62 20 22 24 4a 41  dev/null -b "$JA
16e80 52 53 2f 24 31 22 20 2d 65 20 22 24 55 52 4c 2f  RS/$1" -e "$URL/
16e90 66 6f 72 75 6d 6e 65 77 22 20 2d 2d 64 61 74 61  forumnew" --data
16ea0 2d 75 72 6c 65 6e 63 6f 64 65 20 22 63 73 72 66  -urlencode "csrf
16eb0 3d 24 74 22 20 2d 2d 64 61 74 61 2d 75 72 6c 65  =$t" --data-urle
16ec0 6e 63 6f 64 65 20 22 74 69 74 6c 65 3d 24 32 22  ncode "title=$2"
16ed0 20 5c 0a 20 20 20 20 2d 64 20 6d 69 6d 65 74 79   \.    -d mimety
16ee0 70 65 3d 74 65 78 74 2f 78 2d 6d 61 72 6b 64 6f  pe=text/x-markdo
16ef0 77 6e 20 2d 2d 64 61 74 61 2d 75 72 6c 65 6e 63  wn --data-urlenc
16f00 6f 64 65 20 22 63 6f 6e 74 65 6e 74 3d 24 33 22  ode "content=$3"
16f10 20 2d 64 20 73 75 62 6d 69 74 3d 53 75 62 6d 69   -d submit=Submi
16f20 74 20 22 24 55 52 4c 2f 66 6f 72 75 6d 65 31 22  t "$URL/forume1"
16f30 0a 20 20 6c 61 74 65 73 74 5f 70 6f 73 74 0a 7d  .  latest_post.}
16f40 0a 72 65 70 6c 79 28 29 20 7b 20 23 20 75 73 65  .reply() { # use
16f50 72 20 74 6f 20 63 6f 6e 74 65 6e 74 0a 20 20 6c  r to content.  l
16f60 6f 67 69 6e 20 22 24 31 22 0a 20 20 74 3d 24 28  ogin "$1".  t=$(
16f70 63 75 72 6c 20 2d 73 20 2d 62 20 22 24 4a 41 52  curl -s -b "$JAR
16f80 53 2f 24 31 22 20 22 24 55 52 4c 2f 66 6f 72 75  S/$1" "$URL/foru
16f90 6d 70 6f 73 74 2f 24 32 22 20 7c 20 63 73 72 66  mpost/$2" | csrf
16fa0 29 0a 20 20 63 75 72 6c 20 2d 73 20 2d 6f 20 2f  ).  curl -s -o /
16fb0 64 65 76 2f 6e 75 6c 6c 20 2d 62 20 22 24 4a 41  dev/null -b "$JA
16fc0 52 53 2f 24 31 22 20 2d 65 20 22 24 55 52 4c 2f  RS/$1" -e "$URL/
16fd0 66 6f 72 75 6d 65 32 22 20 2d 2d 64 61 74 61 2d  forume2" --data-
16fe0 75 72 6c 65 6e 63 6f 64 65 20 22 63 73 72 66 3d  urlencode "csrf=
16ff0 24 74 22 20 2d 64 20 22 66 70 69 64 3d 24 32 22  $t" -d "fpid=$2"
17000 20 2d 64 20 72 65 70 6c 79 3d 31 20 5c 0a 20 20   -d reply=1 \.  
17010 20 20 2d 64 20 6d 69 6d 65 74 79 70 65 3d 74 65    -d mimetype=te
17020 78 74 2f 78 2d 6d 61 72 6b 64 6f 77 6e 20 2d 2d  xt/x-markdown --
17030 64 61 74 61 2d 75 72 6c 65 6e 63 6f 64 65 20 22  data-urlencode "
17040 63 6f 6e 74 65 6e 74 3d 24 33 22 20 2d 64 20 73  content=$3" -d s
17050 75 62 6d 69 74 3d 53 75 62 6d 69 74 20 22 24 55  ubmit=Submit "$U
17060 52 4c 2f 66 6f 72 75 6d 65 32 22 0a 20 20 6c 61  RL/forume2".  la
17070 74 65 73 74 5f 70 6f 73 74 0a 7d 0a 54 48 52 45  test_post.}.THRE
17080 41 44 3d 24 28 6e 65 77 5f 74 68 72 65 61 64 20  AD=$(new_thread 
17090 6f 77 6e 65 72 20 22 53 63 72 61 74 63 68 20 74  owner "Scratch t
170a0 68 72 65 61 64 22 20 22 54 68 65 20 66 69 72 73  hread" "The firs
170b0 74 20 70 6f 73 74 2c 20 62 79 20 6f 77 6e 65 72  t post, by owner
170c0 2e 22 29 0a 52 31 3d 24 28 72 65 70 6c 79 20 61  .").R1=$(reply a
170d0 64 61 6d 20 22 24 54 48 52 45 41 44 22 20 22 41  dam "$THREAD" "A
170e0 20 72 65 70 6c 79 2c 20 62 79 20 61 64 61 6d 2e   reply, by adam.
170f0 22 29 0a 52 32 3d 24 28 72 65 70 6c 79 20 73 61  ").R2=$(reply sa
17100 6c 6c 79 20 22 24 52 31 22 20 22 41 20 72 65 70  lly "$R1" "A rep
17110 6c 79 20 74 6f 20 61 64 61 6d 2c 20 62 79 20 73  ly to adam, by s
17120 61 6c 6c 79 2e 22 29 0a 52 33 3d 24 28 72 65 70  ally.").R3=$(rep
17130 6c 79 20 6f 77 6e 65 72 20 22 24 54 48 52 45 41  ly owner "$THREA
17140 44 22 20 22 41 20 73 65 63 6f 6e 64 20 72 65 70  D" "A second rep
17150 6c 79 20 74 6f 20 74 68 65 20 66 69 72 73 74 20  ly to the first 
17160 70 6f 73 74 2c 20 62 79 20 6f 77 6e 65 72 2e 22  post, by owner."
17170 29 0a 70 6f 73 74 73 3d 24 28 66 6f 73 73 69 6c  ).posts=$(fossil
17180 20 73 71 6c 20 2d 52 20 22 24 52 45 50 4f 22 20   sql -R "$REPO" 
17190 22 53 45 4c 45 43 54 20 62 2e 75 75 69 64 7c 7c  "SELECT b.uuid||
171a0 27 20 27 7c 7c 65 2e 75 73 65 72 20 46 52 4f 4d  ' '||e.user FROM
171b0 20 66 6f 72 75 6d 70 6f 73 74 20 66 20 4a 4f 49   forumpost f JOI
171c0 4e 20 62 6c 6f 62 20 62 20 4f 4e 20 62 2e 72 69  N blob b ON b.ri
171d0 64 3d 66 2e 66 70 69 64 20 4a 4f 49 4e 20 65 76  d=f.fpid JOIN ev
171e0 65 6e 74 20 65 20 4f 4e 20 65 2e 6f 62 6a 69 64  ent e ON e.objid
171f0 3d 66 2e 66 70 69 64 20 4f 52 44 45 52 20 42 59  =f.fpid ORDER BY
17200 20 66 2e 66 6d 74 69 6d 65 22 29 0a 5b 20 22 24   f.fmtime").[ "$
17210 28 70 72 69 6e 74 66 20 27 25 73 5c 6e 27 20 22  (printf '%s\n' "
17220 24 70 6f 73 74 73 22 20 7c 20 77 63 20 2d 6c 29  $posts" | wc -l)
17230 22 20 2d 65 71 20 34 20 5d 20 7c 7c 20 7b 20 65  " -eq 4 ] || { e
17240 63 68 6f 20 22 65 78 70 65 63 74 65 64 20 34 20  cho "expected 4 
17250 70 6f 73 74 73 2c 20 68 61 76 65 3a 20 24 70 6f  posts, have: $po
17260 73 74 73 22 20 3e 26 32 3b 20 22 24 44 49 52 2f  sts" >&2; "$DIR/
17270 73 74 6f 70 2e 73 68 22 3b 20 65 78 69 74 20 31  stop.sh"; exit 1
17280 3b 20 7d 0a 0a 23 20 2d 2d 2d 20 61 20 63 6c 6f  ; }..# --- a clo
17290 6e 65 20 6f 76 65 72 20 48 54 54 50 20 61 73 20  ne over HTTP as 
172a0 69 76 79 2c 20 77 69 74 68 20 61 20 63 68 65 63  ivy, with a chec
172b0 6b 6f 75 74 0a 49 56 59 3d 22 24 44 49 52 2f 63  kout.IVY="$DIR/c
172c0 6c 6f 6e 65 73 2f 69 76 79 22 0a 6d 6b 64 69 72  lones/ivy".mkdir
172d0 20 2d 70 20 22 24 49 56 59 2f 74 72 65 65 22 0a   -p "$IVY/tree".
172e0 28 63 64 20 22 24 49 56 59 22 20 26 26 20 66 6f  (cd "$IVY" && fo
172f0 73 73 69 6c 20 63 6c 6f 6e 65 20 2d 41 20 69 76  ssil clone -A iv
17300 79 20 2d 2d 73 61 76 65 2d 68 74 74 70 2d 70 61  y --save-http-pa
17310 73 73 77 6f 72 64 20 22 68 74 74 70 3a 2f 2f 69  ssword "http://i
17320 76 79 3a 24 28 70 61 73 73 77 6f 72 64 5f 6f 66  vy:$(password_of
17330 20 69 76 79 29 40 31 32 37 2e 30 2e 30 2e 31 3a   ivy)@127.0.0.1:
17340 24 50 4f 52 54 2f 22 20 22 24 49 56 59 2f 63 6c  $PORT/" "$IVY/cl
17350 6f 6e 65 2e 66 6f 73 73 69 6c 22 20 3e 2f 64 65  one.fossil" >/de
17360 76 2f 6e 75 6c 6c 29 0a 28 63 64 20 22 24 49 56  v/null).(cd "$IV
17370 59 2f 74 72 65 65 22 20 26 26 20 66 6f 73 73 69  Y/tree" && fossi
17380 6c 20 6f 70 65 6e 20 22 24 49 56 59 2f 63 6c 6f  l open "$IVY/clo
17390 6e 65 2e 66 6f 73 73 69 6c 22 20 3e 2f 64 65 76  ne.fossil" >/dev
173a0 2f 6e 75 6c 6c 20 26 26 20 66 6f 73 73 69 6c 20  /null && fossil 
173b0 75 73 65 72 20 64 65 66 61 75 6c 74 20 69 76 79  user default ivy
173c0 20 26 26 20 66 6f 73 73 69 6c 20 73 65 74 74 69   && fossil setti
173d0 6e 67 73 20 61 75 74 6f 73 79 6e 63 20 6f 66 66  ngs autosync off
173e0 29 0a 0a 63 61 74 20 3e 20 22 24 44 49 52 2f 65  )..cat > "$DIR/e
173f0 6e 76 2e 73 68 22 20 3c 3c 45 4f 46 0a 23 20 2e  nv.sh" <<EOF.# .
17400 20 24 44 49 52 2f 65 6e 76 2e 73 68 20 20 20 2d   $DIR/env.sh   -
17410 2d 20 66 6f 72 20 74 65 73 74 65 72 73 3a 20 74  - for testers: t
17420 68 65 20 73 63 72 61 74 63 68 20 48 4f 4d 45 2c  he scratch HOME,
17430 20 6f 63 78 32 20 6f 6e 20 50 41 54 48 2c 20 74   ocx2 on PATH, t
17440 68 65 20 73 65 72 76 65 72 27 73 20 55 52 4c 0a  he server's URL.
17450 65 78 70 6f 72 74 20 48 4f 4d 45 3d 22 24 44 49  export HOME="$DI
17460 52 2f 68 6f 6d 65 22 0a 65 78 70 6f 72 74 20 50  R/home".export P
17470 41 54 48 3d 22 24 44 49 52 2f 62 69 6e 3a 5c 24  ATH="$DIR/bin:\$
17480 50 41 54 48 22 0a 65 78 70 6f 72 74 20 55 52 4c  PATH".export URL
17490 3d 22 24 55 52 4c 22 0a 65 78 70 6f 72 74 20 52  ="$URL".export R
174a0 45 50 4f 3d 22 24 52 45 50 4f 22 0a 45 4f 46 0a  EPO="$REPO".EOF.
174b0 0a 7b 0a 20 20 65 63 68 6f 20 22 75 72 6c 20 24  .{.  echo "url $
174c0 55 52 4c 22 0a 20 20 65 63 68 6f 20 22 6f 63 78  URL".  echo "ocx
174d0 5f 70 61 67 65 20 24 55 52 4c 2f 65 78 74 2f 6f  _page $URL/ext/o
174e0 63 78 32 2d 63 67 69 22 0a 20 20 65 63 68 6f 20  cx2-cgi".  echo 
174f0 22 72 65 70 6f 73 69 74 6f 72 79 20 24 52 45 50  "repository $REP
17500 4f 22 0a 20 20 65 63 68 6f 20 22 73 65 72 76 65  O".  echo "serve
17510 72 5f 63 68 65 63 6b 6f 75 74 20 24 43 4f 22 0a  r_checkout $CO".
17520 20 20 65 63 68 6f 20 22 63 6c 6f 6e 65 5f 69 76    echo "clone_iv
17530 79 20 24 49 56 59 2f 63 6c 6f 6e 65 2e 66 6f 73  y $IVY/clone.fos
17540 73 69 6c 22 0a 20 20 65 63 68 6f 20 22 63 68 65  sil".  echo "che
17550 63 6b 6f 75 74 5f 69 76 79 20 24 49 56 59 2f 74  ckout_ivy $IVY/t
17560 72 65 65 22 0a 20 20 65 63 68 6f 20 22 70 72 6f  ree".  echo "pro
17570 67 72 61 6d 20 24 44 49 52 2f 72 6f 6f 74 2f 63  gram $DIR/root/c
17580 75 72 72 65 6e 74 2f 6f 63 78 32 20 28 63 6f 70  urrent/ocx2 (cop
17590 79 20 6f 66 20 24 53 54 41 47 45 44 2c 20 73 68  y of $STAGED, sh
175a0 61 32 35 36 20 24 28 73 68 61 32 35 36 73 75 6d  a256 $(sha256sum
175b0 20 22 24 53 54 41 47 45 44 22 20 7c 20 63 75 74   "$STAGED" | cut
175c0 20 2d 64 27 20 27 20 2d 66 31 29 29 22 0a 20 20   -d' ' -f1))".  
175d0 65 63 68 6f 20 22 74 69 63 6b 65 74 20 24 54 49  echo "ticket $TI
175e0 43 4b 45 54 22 0a 20 20 65 63 68 6f 20 22 74 68  CKET".  echo "th
175f0 72 65 61 64 20 24 54 48 52 45 41 44 22 0a 20 20  read $THREAD".  
17600 65 63 68 6f 20 22 72 65 70 6c 79 5f 61 64 61 6d  echo "reply_adam
17610 20 24 52 31 22 0a 20 20 65 63 68 6f 20 22 72 65   $R1".  echo "re
17620 70 6c 79 5f 73 61 6c 6c 79 5f 74 6f 5f 61 64 61  ply_sally_to_ada
17630 6d 20 24 52 32 22 0a 20 20 65 63 68 6f 20 22 72  m $R2".  echo "r
17640 65 70 6c 79 5f 6f 77 6e 65 72 20 24 52 33 22 0a  eply_owner $R3".
17650 20 20 65 63 68 6f 20 22 77 69 6b 69 20 4e 6f 74    echo "wiki Not
17660 65 73 22 0a 20 20 70 72 69 6e 74 66 20 27 25 73  es".  printf '%s
17670 5c 6e 27 20 22 24 63 68 65 63 6b 69 6e 73 22 20  \n' "$checkins" 
17680 7c 20 74 72 20 2d 64 20 22 27 22 20 7c 20 73 65  | tr -d "'" | se
17690 64 20 27 73 2f 5e 2f 63 68 65 63 6b 69 6e 20 2f  d 's/^/checkin /
176a0 27 0a 20 20 65 63 68 6f 20 22 6e 6f 62 6f 64 79  '.  echo "nobody
176b0 5f 63 61 70 73 20 24 28 66 6f 73 73 69 6c 20 73  _caps $(fossil s
176c0 71 6c 20 2d 52 20 22 24 52 45 50 4f 22 20 22 53  ql -R "$REPO" "S
176d0 45 4c 45 43 54 20 63 61 70 20 46 52 4f 4d 20 75  ELECT cap FROM u
176e0 73 65 72 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d  ser WHERE login=
176f0 27 6e 6f 62 6f 64 79 27 22 29 22 0a 20 20 65 63  'nobody'")".  ec
17700 68 6f 20 22 61 6e 6f 6e 79 6d 6f 75 73 5f 63 61  ho "anonymous_ca
17710 70 73 20 24 28 66 6f 73 73 69 6c 20 73 71 6c 20  ps $(fossil sql 
17720 2d 52 20 22 24 52 45 50 4f 22 20 22 53 45 4c 45  -R "$REPO" "SELE
17730 43 54 20 63 61 70 20 46 52 4f 4d 20 75 73 65 72  CT cap FROM user
17740 20 57 48 45 52 45 20 6c 6f 67 69 6e 3d 27 61 6e   WHERE login='an
17750 6f 6e 79 6d 6f 75 73 27 22 29 22 0a 7d 20 3e 20  onymous'")".} > 
17760 22 24 44 49 52 2f 66 61 63 74 73 2e 74 78 74 22  "$DIR/facts.txt"
17770 0a 0a 65 63 68 6f 20 22 72 65 61 64 79 3a 20 24  ..echo "ready: $
17780 55 52 4c 20 28 70 69 64 20 24 28 63 61 74 20 22  URL (pid $(cat "
17790 24 44 49 52 2f 73 65 72 76 65 72 2e 70 69 64 22  $DIR/server.pid"
177a0 29 29 3b 20 70 61 73 73 77 6f 72 64 73 20 69 6e  )); passwords in
177b0 20 24 44 49 52 2f 70 61 73 73 77 6f 72 64 73 2e   $DIR/passwords.
177c0 74 78 74 3b 20 66 61 63 74 73 20 69 6e 20 24 44  txt; facts in $D
177d0 49 52 2f 66 61 63 74 73 2e 74 78 74 3b 20 73 74  IR/facts.txt; st
177e0 6f 70 20 77 69 74 68 20 24 44 49 52 2f 73 74 6f  op with $DIR/sto
177f0 70 2e 73 68 22 0a 00 00 00 00 00 00 00 00 00 00  p.sh"...........
17800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17810 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17820 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17830 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17840 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17850 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17860 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17870 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17880 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17890 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
178f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17900 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17910 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17920 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17930 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17940 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17950 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17960 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17970 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17980 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
179f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17a90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17aa0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17ab0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17ac0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17ad0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17ae0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17af0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b50 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17b90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17ba0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17bb0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17bc0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17bd0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17be0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
17bf0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................