Wednesday, June 12, 2019

It's official!!

My name is officially Jennifer Kathryn Stafford! This is a huge relief to me - seeing my old name is a major trigger for dysphoria. There are still a lot of places where it needs to be updated, and that old name is going to be popping up like a cockroach infestation for years to come. Maybe one day I can disassociate myself from it, but that's a long way away.

Unfortunately, since I was born in Kansas, I am currently unable to correct my birth certificate. There is a federal lawsuit, Foster v. Andersen, filed last October, which is still working its way through the courts. With Brownback gone, there is a slim chance that this discriminatory policy could be corrected legislatively, but I'm not holding my breath for that.

Wednesday, May 22, 2019

Dragon cuddles!

I had this artwork commissioned of me with my cuddly dragon boyfriend, Scrydan. You can view the full image here, but beware that it may be slightly NSFW.

Artwork © 2019 by Vallhund

Thursday, May 16, 2019

Hello World! I'm Katie.

A month ago, I posted about changing my name on all my accounts to just my initials. This was just temporary. Now I can finally reveal my shiny new name:

[Jeff Goldblum] Well, there it is.

I've been going by "Katie" privately for about a month and a half now. Online, I've been going by my fursona's name "Katie Pendry", or "Katie the Panda", or "ktpanda". My site is now, and all the old URLs will redirect to the new one.

Needless to say, I'm still the same person, except now I can be who I truly am and not feel like I'm wearing a mask all the time.

I'd like to thank the Reddit communities /r/egg_irl, /r/traaaaaaannnnnnnnnns, and /r/MtF. as well as my wonderful therapist, for helping me kick my self-doubt and denial, and for showing me that every trans person's experience is different. I had built up a straw person view of what a trans person must experience, and simply dismissed all the thoughts that I might be trans because I obviously didn't meet all this strict criteria, and must therefore I must be a cis male.

Despite the fact that I've always wanted smooth, soft skin.

Despite the fact that I've despised having facial and chest hair, always keeping it shaved as short as possible, even though I hate shaving.

Despite the fact that I've always hated my voice.

Despite the fact that as a kid, I fantasized about swapping bodies with a girl in my class.

Despite the fact that I found the idea of magical transformation into a woman appealing.

Despite the fact that I once accidentally introduced myself as my mom's daughter (brain fart or subconscious wishing? I'm still not sure).

You get the picture.

But after seeing the memes on /r/egg_irl, talking to other trans people, and talking with my therapist, I came to the conclusion that whatever I ended up as, I wasn't 100% cis. I picked out a name, created a new Reddit account, and started exploring. I started taking hormones on April 24, and within a week, it was clear - I'm not genderfluid, non-binary, or any of the other labels I was trying out... I'm a girl, plain and simple.

All the friends I have come out to so far have been extremely supportive, and I am very grateful for that. I know it's not easy adjusting to a change like this, but they have been very good about using my new name and not misgendering me.

Finally, I am very thankful for the support of my loving boyfriend, Scrydan. He has been a huge source of support during my transition. It's so helpful to not have to worry about whether or not my partner will support me.

Friday, May 10, 2019

Quick update

Back in February, I promised to start blogging more often. I haven't had a lot of time to keep up with it, though. I've been spending a lot of time with my boyfriend Scrydan who I met at TFF. Even though we live a fair distance apart, we're spending as much time together as we can. This weekend, we're going to be camping at Central Plains Fur Meet southwest of Wichita.

Posts might be sparse for a bit, but hopefully I'll have some stuff to post about soon.

Friday, April 19, 2019

So what's up with the name change?

I've been trying out just using my first and middle initials instead of my full name. It's not that I don't like my name, I just wanted to try something new. Plus, it puts me in good company.

Now if you'll excuse me, I have to go yell at my engineers, who so far have completely failed to create the combustible lemons I requested...

Monday, April 01, 2019

Photos from Texas Furry Fiesta 2019

Well, TFF is over, and I had a blast! Thanks to @Skywind_Kitsune for driving me down there and back. This was my first furry convention, and I look forward to going to many more.

Here are a few photos that I got. Unfortunately, I didn't get names of everybody that I got photos of, so if you recognize someone, please let me know!

My friend Hexadoodle in the fursuit playground.
Fursuit Improv
On the observation deck of Reunion tower.
Me with CandyPaws
Playing with a pizza frisbee

Thursday, March 21, 2019

My first fursuit

Yesterday, I received my first fursuit for my character Jace Pendry from GEEKpaw productions, and I love it! It fits pretty well, although it's a little tight. It gets hot inside, as expected, which is why I bought an EZcooldown cooling vest.

I can't wait to show it off at TFF next week!

Friday, March 15, 2019

"Have you tried turning it off and on again?" "Yes, my robot did"

Ok, so it's not quite a robot, but it is automated...

Yesterday while I was at work, there was a power failure at home that lasted longer than my UPS could handle. My server shut down, and when it came back up after the power was restored, it couldn't get online. The problem that I discovered after I got home was that the cable modem had stopped responding to DHCP requests, pings, or anything. The solution to this was simple - unplug it and plug it back in.

But what if something like this happens when I'm out of town? I need some way of resetting it without being physically present. I realized I already had the components to hack together a solution - I had a relay module from an Arduino kit, an Arduino already up and running controlling my air conditioner via an IR LED, and jumper wire. I even had a script monitoring the internet connection already running on the server, but all it could do at that point is force the server to re-request DHCP. All I needed to do was cut the low-voltage wire for the power adapter, connect the cut ends to the Common Normally Closed terminal of the relay, then wire it to my Arduino. That proved a bit challenging, because the Arduino has to be in a spot where its LEDs have line-of-sight to my air conditioner, but I don't want to put the modem right there. I had to chain together several individual jumper wires to get it to reach, and I may re-visit that design in the future.

So then it's just a matter of writing the software. I modified my existing Arduino sketch to pull a GPIO high most of the time, but when it receives a command over USB serial, pulls it low for 5 seconds. The relay module has a P-channel MOSFET controlling the relay, so it is active-low. When the relay activates, it disconnects the Normally Closed circuit and the modem reboots. I set up my monitoring software so that if it can't ping the modem for a period of 90 seconds, it resets. While the modem is connecting, it hands out a local IP address of, so I can still ping it and grab the status. It also resets the whole thing if it boots up, but doesn't come online within 4 minutes.

It's not the most hacky solution I've come up with so far, but it's close.

Sunday, March 03, 2019

Volt mod: Forcing brake lights on in "L" mode

The Volt has a standard 5-position gear selector lever, with Park, Neutral, Reverse, Drive, and "Low". It doesn't make much sense for a hybrid or electric transmission to have a "Low" position, but like other manufacturers, GM has chosen to implement it in a way that simulates the same kind of engine braking that you would get from a traditional transmission. Unlike a traditional powertrain, there is no issue with leaving it in this position while driving at high speeds. It does this by changing the mapping on the accelerator pedal. In "D", it will apply a small amount of regenerative braking (about 2.5 kW) to slow the car down a bit. In "L" mode, it applies a larger amount of braking (30 kW). This can quickly slow the vehicle almost to a stop.

The only issue is that it doesn't turn the brake lights on when you do this! This can lead to a situation where the car is decelerating quickly, but but the vehicles behind don't notice.

So I had an idea... I can certainly detect the conditions under which the car is slowing down, but how can I turn on the brake lights? It turns out there are diagnostic commands that can be sent over the OBD2 port to turn each individual light on for testing. So the conditions I need to check are:

  1. Gear selector is in "L" position,
  2. Accelerator pedal is less than 5% pressed, and
  3. Cruise control is not active.

I feel a lot safer driving in "L" mode with this hack in place. Although this would not have stopped that kid from rear-ending me - that happened at a stoplight with the brakes pressed.

Thursday, February 28, 2019

Cursing at ncurses

I've just spent the last hour and 45 minutes debugging a really strange problem I encountered after updating my server to Ubuntu 18.04. Whenever I use ncurses-based programs within tmux, sometimes the text would display strangely, as if the cursor were in the wrong place. Now, it's not immediately obvious who is at fault here - there are three completely different terminal emulators at play here. The program I am running is ncdu (ncurses disk usage), which sends its output to tmux, which is running under mosh, and is finally rendered by xterm.

I was quickly able to determine that the problem must lie between ncdu and tmux, because switching tmux to a different window and switching back did not fix the problem. I also verified this by doing tmux capture-pane -p, and it indicated that everything I was seeing was exactly now tmux was drawing it.

So what changed? Well, ncdu and ncurses both got upgraded. I'm still using my old custom-compiled tmux, though, so something must have changed in the way ncdu communicates. I suspected one of two things: either something else was writing to the terminal, or ncurses had been upgraded to a version that is more "clever" about the way it draws the screen. Luckily, tmux has a feature to log all terminal output to a file, so I was able to replay it. I wrote a quick Python script to slowly dump the log to the terminal, byte by byte, so I can pinpoint what it is sending when the problem occurs:

What I found out was that when I press Page Down, it was sending a command to scroll a region of the screen: \033[11S. However, tmux didn't seem to understand this instruction, and just ignored it. I verified this by looking at the source itself.

So what could I do? I could just use the normal version of tmux from the Ubuntu repository. It's a newer version that does support the scroll command, but the reason I switched back to the old version is because the newer version was crashing. I'd rather use an older, stable version than deal with crashes that take out all my sessions. So the only chance is to convice ncdu not to send the scroll command. Since ncdu uses ncurses, which reads a database of command codes for different terminal types. What I ended up having to do was:

  1. Download ncurses.
  2. Edit misc/terminfo.src, and remove indn=\E[%p1%dS, from the screen section.
  3. Run tic terminfo.src to convert it to the binary format read by ncurses.

This is the kind of problem that I enjoy solving. A subtle bug, which doesn't endanger my data, but is just annoying enough to fix, and has a root cause that is easy to understand - and not just a stupid mistake on my part.

Sunday, February 24, 2019

Time for an upgrade

Last evening, at 21:00, my server (marvin) powered off for no reason. Well, it happens. No reason to be worried, right? Well, earlier this morning, at 00:38, it did it again. So it's dying. It's time for an upgrade, anyway... It's using a motherboard I bought in 2010 and an AMD Phenom II X4 CPU that I bought in 2011. I bought an AMD Ryzen 7 2700X processor, 16GB DDR4 memory, and an MSI X470 Gaming Plus motherboard. It's not going in marvin, though - I don't need that much power for what I'm using it for. No, the new stuff is for arthur, my gaming desktop. Like I did 4 years ago, marvin is getting arthur's old motherboard. In fact, I ended up just sticking marvin's boot drive in arthur's case, since that was much easier that swapping a motherboard, and I don't actually need to run arthur most of the time. The only thing I was using it for most of the time was to watch videos, and I don't need a super powerful CPU and video card for that. In the meantime, I've set up marvin to run X so I can at least do what I've been doing until the new stuff arrives.

I actually like this arrangement because it is more efficient - I don't need to have two power-hungry systems running all the time. A few months ago, I actually tried replacing arthur with the Raspberry Pi 3 B+ that I ended up using in my Volt mod project. The only reason it didn't work is because it struggled to play 1080p videos. I don't know why I didn't think of just using marvin as a media player - it already does so much other stuff, surely it can handle one more task. I may keep arthur turned off more often even after I get it set up.

One complication is the fact that arthur's old motherboard doesn't have a header for a parallel port, which I was using to run my super-old automation system that I built in 2008, using the data pins of the parallel port as 5v GPIO. I could just wire it up to my Arduino, but that would be more than I'm willing to invest in that project. I'd rather build something from scratch than put any more work into it. So I just ordered a PCIe parallel port card. Hopefully, it will work just the way it did before.

I'm also in the process of upgrading marvin to Ubuntu Server 18.04. I've got another (bigger) SSD boot drive that I've installed a clean image of 18.04 onto, and I'm slowly getting services up and running on it using a VM. It's still not ready, though, so I'm still stuck on 14.04 for now. It's going to be EOL soon, though. I definitely understand the upgrade fears - it used to be that I was always eager to try out the latest stuff, even if I had to compile it from source, because fixing it when it broke was an adventure. Now, I want it to just work the same way it always did before.

Saturday, February 23, 2019

How I remember all my passwords

Most password managers are based on the same basic idea - you remember one password, you put that into your password manager, and it spits out your plaintext passwords for all the sites you visit. This is fine for sites you don't visit a lot and don't need high security for.

But I wanted to be able to just remember my passwords. So I created Brain Password Manager, which allows me to practice entering passwords on a schedule, so I don't forget them.

BPM doesn't actually store my passwords. Instead, it runs the passwords through a very large number of calculations (800,000 rounds of PBKDF2) to arrive at a number between 0 and 4095. This number is the only information it stores.

When you practice entering your passwords, it does the same calculations. If the resulting number is different, then your definitely typed your password wrong. But, if you enter any password at random, there is a 1 in 4096 chance that it will still say you are correct. This isn't very likely to happen due to a simple typo in your password, though.

What this means is that any attacker trying to extract your passwords will find that lots of passwords match, and has no way of proving which one is the real password, other than trying it out on the site that the password is for. In fact, BPM has a built-in feature which finds false positives for a password to demonstrate just how many passwords an attacker would have to try.

I even created a utility to bruteforce false positives, which demonstrates just how many passwords an attacker would have to try:

All of these passwords will be accepted as correct.

I still use a regular password manager for sites which I rarely log into. BPM is mainly for passwords that I enter frequently enough that a password manager is a hassle, but not frequently enough that I don't forget the password.