• 0 Posts
  • 151 Comments
Joined 3 years ago
cake
Cake day: June 30th, 2023

help-circle



  • Firefox Nightly + arkenfox userjs + uBlock Origin + Bitwarden as my daily driver.

    Been a couple years since I checked up on arkenfox still being good. I get flagged as a bot all the time and constantly get popups about WebGL (GPU fingerprinting) so I assume its working as intended for my threat model.

    Tails when I really care.

    Mullvad VPN as my regular VPN with ProtonVPN for torrents.

    GrapheneOS / NixOS as my OS.

    Proton Visionary for most cloud services except passwords and I don’t really use Proton Drive. I do use ProtonPass for unique emails to every provider.

    Kagi for searches / AI.

    Etesync for contacts because Proton didn’t sync with the OS last I checked.

    Backblaze B2 for cloud storage with my own encryption via rclone (Round Sync on GrapheneOS)

    Keypass for a few things like my XMR wallets and master passwords I don’t even trust in Bitwarden.

    https://jmp.chat/ for my mobile provider.

    Pihole with encrypted DNS to Quad9.

    https://onlykey.io/ for the second half of my sensitive passwords (Bitwarden, LUKS, Keypass, OS login). First half memorized.

    Its a lot. I burned myself out a couple years ago keeping up with optimizing privacy and this setup has served me well for 2 years without really changing anything. The cloud services are grey areas in terms of privacy but the few ads that leak through uBlock have zero relevance to anything about me.


  • BSP Tree (with custom nodes).

    With a vanilla BSP-tree you can accomplish your diagram. Simply reordering your splits can do it by making the footer and main content areas first. Better approach is to support splits on non-leaf nodes. In the example below just split the root where all its children go to the new top node and a new bottom bar leaf node is created.

    Root (split: vertical, ratio: 0.6)
    ├── Left child (Window A)
    └── Right child (split: horizontal, ratio: 0.5)
        ├── Top child (Window B)
        └── Bottom child (Window C)
    

    To access neighbors you’ll need your nodes to track their parents (double linked). Then you can traverse until all edges are found. Worst case its O(height+num neighbors that exist) if I am remembering.

    Depending on how efficient you want it to be, there are speed ups. It has been awhile, but I do remember keeping the tree as balanced as possible makes the search around log(n). Each split node keeping an index of all children in its sub-tree also reduces how much traversing is needed when you need all children after a split.

    Can get a little complicated but it is doable. That said, how many splits will a TUI have? This may be preemptive to do.

    Custom nodes is where you support some patterns that could use further optimizations. Tables that will always be a grid. Tab bars that are a 1xn grid could be a further specialized node.

    This is all about layout. Fixed/Dynamic width/height windows, padding and margins, borders, are all render processing and don’t effect the layout (unless you want reactivity). By that I mean you have windows that will split differently when the viewport is portrait or landscape and it dynamically adjusts to the window size. Sometimes with different “steps” like a square viewport may be different from both portrait or landscape or 4:3 could be treated different from 16:9.

    TUIs are not my day job but I’ve made a few in my day. Above are just my opinions from experiences. There is no “right” answer but hopefully some of this helps your journey.


    TypeScript is my day job and using a custom JSX Factory makes it pretty easy to define HTML-like interfaces for devs that can support mixing layout, render attributes, content, and app logic.

    Explicit BSP splits:

    <Split type="vertical" ratio={0.6}>
      <WidgetA />
      <Split type="horizontal" ratio={0.5}>
        <WidgetB />
        <WidgetC />
      </Split>
    </Split>
    

    Custom nodes:

    <Container>
      <TabBar>
        <Tab>Tab 1</Tab>
        <Tab>Tab 2</Tab>
      </TabBar>
      <StatusBar />
    </Container>
    

    Not sure your stack but throwing it out there as something I’ve used successfully.










    1. Not sure on this one.

    2. The auditor is to make sure you are installing an authentic version of graphene. That it is not a modified version that has been tampered with (e.g., backdoors).

    3. Automatically enables MAC randomization. This can help with being tracked on public networks. Fingerprinting techniques have gotten better though with deep packet inspection and even measuring radio characteristics. I’ve seen demos of two brand new and identical models of iPhones being distinctly picked out due to variances in the radios during manufacturing.

    Doesn’t help with advertisers tracking behavior based on IP. VPNs help with “blending-in” by putting multiple users behind the same IP. Provider matters here. Needs to be a VPN provider that won’t just sell your data or cave to law enforcement. Mullvad is my preference. Paid with crypto. RAM only logs. That said, use Tor or I2P for anything you don’t want subpoenaed.

    For additional tips:

    • Can’t remember if its on by default, but auto-reboot to put data at rest (encrypted and not in RAM). This is for a state-actor threat level, and less about advertisers.
    • I prefer pin codes to unlock my device and don’t use biometrics. Graphene has a feature to randomize the pin pad every time to protect against a recording of the pin be entered. Specifically where the numbers aren’t picked up on the video but the pattern your hand makes can be seen. Again, more of a state-actor threat level.




  • There is anonymity and pseudonymity.

    Do you need your opsec to be resistant to state-level actors (oppressive regime, censorship, illegal activities)? Well then you need to make sure you don’t introduce anything that will deanonomize you.

    Are you trying to be resistant to mass data collection efforts used for profit? Being on the pseudonymity spectrum is a good step.

    Dealing with the latter is like dealing with a bully. Make it not worth their time. They just want to put you in bucket X so they can estimate the most likely way to influence you for reason Y. Pseudonymity is about having multiple aliases that get put into different buckets so their privacy invasive efforts are less effective.