Posts by Shawn McKinney

A bike riding code monkey.

Upgrade from javax to jakarta — not yet!

It’s now been almost five years since Oracle announced the donation of Java’s enterprise layer to the Eclipse foundation. It stipulated a name change, removing “Java”, ostensibly due to trademark issues. Eclipse chose “Jakarta” as the new name.

As Java programmers, we understand organizational boundaries of dependent modules are enforced via package names. How we reference them in our code.

For many years now we’ve had this durable base of auxiliary software coming from the platform and the 3rd parties that comprise its ecosystem. It’s free and shields us from the intricacies and accelerates development. Makes our job easier. The reason I continue to use Java.

The programming language itself factors into why we choose to use it too. Java ranks at or near the top, in my estimation. We’re not discussing theory or practice here and I’m not trying to convince you the platform’s viable.

Back to the main point. There’s a cost associated with using free software, despite the language in which it was written. Sometimes it changes. Always for reasons outside of our control. That means we must change our code to accommodate. The Jakarta migration requires that millions (billions?) of lines-of-code be changed. We’re talking about the biggest disruption to the Java ecosystem in its 27 years.

Not a rant-post and we’re not going over tactics here. That has all been covered elsewhere. I will point out that converting the code is simple. Just change the package imports and pull in the newer versions of the libs into whatever dependency mechanism is being used.

If you can find all of them. As of today, many affected suppliers have published Jakarta compatible releases, some are still working on it, while still others have it on their roadmap.

That’s quite remarkable actually and demonstrates the robustness of the ecosystem. It’ll handle it — eventually.

The runtime’s ready, with a logjam in the projects upstream. Until all of the projects we use have published their compatible packages, we can’t migrate. In turn projects dependent on us must wait until we publish our conversion, and so on. We can replace our non-compliant libraries (a ton of work) or wait.

What’s hanging in the balance is which Servlet container runs and which version of the JVM will be in use. Older code can’t run in newer containers and vice versa. There are ways to sidestep the compatibility restrictions. Conversion routines that modify the packaged bytecode so it works with the jakarta namespace. Can you say shim? For me, I’ll wait just a bit longer. Hope it doesn’t take too long.

These Lessons Anecdotal (Ode to Stack Overflow)

Played to the tune of “Message In A Bottle” by The Police

Just a question say, I’m completely in the trees, so
Another bug in the way, so c’mon help me please, oh
More erroneous than any scan can take
Rescue me before I lose my hair, oh

I’ll dump questions on the world
I’ll send dumb questions to the world
I hope that someone sees mine
I hope that someone knows mine
I hope that someone answers mine
Your guess is anecdotal, yeah
And these guesses cause me trouble, yeah

A week has gone since I wrote my post
I should have known this right from the start
Only hope can keep me together
Just a little luck and then we can release
No luck at all means we’re fucked

I’ll dump questions on the world
I’ll send dumb questions to the world
I hope that someone gets mine
I hope that someone knows mine
I hope that someone answers mine

Your guess is anecdotal, yeah
And these guesses cause me trouble, yeah
So, don’t be guessing on my post, no

Googled again this morning, can’t believe what I saw
Hundred billion questions popped into my chrome
Seems I’m not the only one that’s confused
Hundred billion other people, still searching for a clue

The Long Voyage

It sounded good at the time. Fueled by the liquid courage a few IPA’s brings during the cold winter month’s planning of the summer’s upcoming events. I received the invitation to enter a new ride, called The Long Voyage.

The courage lasted until this arrived in my inbox:

Congratulations! You have been selected as one of the 100 riders for the inaugural Gravel Worlds: The Long Voyage sponsored by Komoot! This event will challenge your mind, body, and spirit and we can’t wait to hear and see your adventures!”

Oh, crap. 300 miles across some of the most godforsaken roads in the Midwest. Set to take place in late August, long before the summer heat has subsided.

My last Gravel Worlds was in ’19. Finished the 150 mile gravel event in just over 13 hours. Crossed the line and had to sit down for a few minutes (first time ever). Walked to my truck, drove 1000 meters, pulled over and lost my cookies. That was my finish line experience.

The Long Voyage is 2X that distance. 30 hours to complete, start at 5pm, ride all night and the next day. What have I gotten myself into?


Knew I had to step up my game. The last couple of years has been a struggle on the longer events, which have been described in painful detail here. The problem’s called ‘rot gut’. Get halfway into an all day event and stomach stops working leading to all sorts of difficulties.

So, I hired a coach, Frank Pike, and started working on a structured training plan. I also worked on my hydration strategy, experimenting with various mixes.

Things were going pretty good. I was getting stronger and headed for the first big challenge of 2021: Unbound’s 200 miler in the Flint Hills of Kansas, the week after memorial day (June 2).

Unbound Gravel a.k.a Dirty Kanza

Being a 4x finisher, my confidence was high. That lasted for all of about 70 miles, until the heat kicked up and I found myself struggling to keep a proper pace. Things came to a head at mile 125 at the 2nd neutral water stop in Alta Vista.

Little Egypt Road, mile 75

“Good job, you made it just under the cutoff!”, the volunteer stated as I arrived. Oh, crap. Just Under The Cutoff. Barely able to maintain 10 mph and facing a stiff headwind home. I pulled the plug. My first-ever DNF at DK.

I was bummed, but remained resolute in fixing the problems and not giving up. Frank introduced me to an expert in sports nutrition, Nicole Rubenstein, who helped me determine my sweat rate and calculate a proper level of intake of electrolytes.

The problem is called hyponatremia and occurs when the sodium level in the blood is too low. I was taking in proper amounts of fluids, but not adding enough electrolytes. I started taking 340mg salt capsules in addition to what’s in my drink mixes.

Another area that I needed work on being calorie intake. It was tough to find something that’s tolerated over the course of a race, say 12, 16, 20 and with my upcoming ride, 30 hours. Under Nicole’s direction I started rolling plain white bread into little balls, and carrying in ziplock bags. One slice is 120 calories, easy to carry and well tolerated.

More Training

In the weeks leading up to The Long Voyage the training miles increased. 300, 400 miles per week. Back-to-back centuries, double centuries, all night rides, midday rides (in the heat) were part of the plan. Also continued with the structured intervals on the trainer.


A couple of weeks before The Long Voyage I felt good. I tapered my training under Frank’s direction. Rest was a priority as was eating right and avoiding things like beer.

Starting Line

At 5pm the weather was hot. But, a front passing through would bring some rain and cooler temps before nighttime. Frank provided last minute instructions. My buddies, Dawn, Jerry and Mike, were riding Saturday and there to provide encouragement. I lined up with the 70 or so other riders and we’re off.

Most of the others, say 50, were much faster and sped off into the distance. That was fine by me. It’s a long ride. No need to hurry. My goal was to maintain a leisurely pace, between 12 and 14 miles an hour. There were about 20 others that remained in the back. We had pleasant conversations and played leapfrog until the storm hit.

I’m pretty comfortable in the rain, and so didn’t have any problems when it hit. Fortunately, no lightning and most of the roads were fine.

Just before the rain

First Stop

When night fell the rains had stopped. I rolled into the first stop, Weeping Water (no pun intended), around 9:30 pm (mile 54). Because The Long Voyage is unsupported, the stops were convenience stores in small towns. I refueled and hit the road again, feeling pretty good.

The first minimal maintenance road (MMR) was just before the second stop, outside Syracuse. MMR’s are lightly maintained. Graded occasionally, but gravel is not laid. This means they get muddy. The consistency of the mud can be described as peanut butter. Very sticky, it will quickly build and make riding impossible. Try to ride it, and a derailleur or the chain will break.

That first MMR was rideable because the rain over this section was not heavy, but it was an indication of what’s coming.

Second Stop

The next stop was a Loves truck stop (mile 80) just outside of Syracuse, Nebraska. We first saw its giant sign 10 miles away but it would disappear and reappear again as we descended and climbed the hills.

I rolled in about midnight and so far things were according to plan. Refueled and enjoyed a treat of fresh pineapple and was on my way again in about 15 minutes.


Leaving the truck stop I flubbed hopping a curve, hit it head-on and did an endo (back wheel raises up and over) and dropped it hard on the concrete. It was embarrassing as there were maybe a dozen riders who were sitting outside and witnessed it. One helped me get up. I thanked him as I assessed the damage. Besides my pride, I noticed one of my aerobars got knocked loose. After readjusting and tightening I rode off again.

Back on the road is when I realized the bike’s derailleur was damaged and returned to the truckstop. As I fiddled with the derailleur the chain came off and got twisted in the spokes of the rear wheel.

When it hit that this ride might be over. A long way back to Lincoln (60 miles) and I had no way to get there. I was bummed. How could things get so bad after being good just minutes before?

GPS track at mile 80 included two false starts

Calm Down

Eventually, my mind eased and I worked the problem getting the chain back on again and reassessed the situation. I don’t have gears 4 – 9, but I do have 1-3 and 10-12. I can make this work.

Off Again

Now 1:00 am and in dead last place I took off again. It was a tough decision, leaving the relative comfort of Syracuse into the darkness, knowing my bike could break down at any time leaving me stranded.

During the first half hour, I beat myself up. The skies had cleared and a nearly full moon had emerged. We had a candid discussion about competency, i.e. the lack of. Eventually, I got over it and found a rhythm. Not having the middle gears was a setback. It meant either standing up in tall gears or spinning in short ones.

My chances to finish were slim, average speed had dropped to around 10 mph and I lost an hour at the truckstop. Oh well, shit happens. Find something to like about it.


About 4:30 am (mile 115) a truck approached me with their bright lights on. “Turn your f***ing brights off”, I muttered to myself. The truck slowed as it passed and a man stuck his head out the window.

“Hey!”, he greeted, before this…


I could tell there were others inside the cab with him. These hicks must have been up all night drinking and who knows what else. I wasn’t in the mood to discuss, on friendly terms or otherwise, lowered my head and kept riding. Fortunately, they drove off.


Soon, I rolled into Adams (mile 120). Blink, and you miss it (even on a bike). I passed the closed convenience store and heard shouting from a block down a side street. I looked and saw two riders in a dark parking lot. This was our refueling station. I would have missed it if they hadn’t called out. There were cases of bottled water stacked up, a water hose, paper towels, an air pump and some misc tools.

I got reacquainted with Molly and Steve. We met over the first 50 miles of the course. Molly was upset and told us about being harassed by the rednecks. They stalked her and tried to run her off the road. She called 911 and a deputy showed up. He told her boys will be boys. I would have been pissed too. She didn’t know what to do next.

“You can ride with us”, Steve said.

“Yeah, you can ride with us”, was my reply.

Before we left, we spent time getting our bikes cleaned up, mud out of the chains, gears and brakes.

“Thanks for letting me ride with you guys”, she said.

I had already figured out that she was a badass and so it’s not like we were doing her any favors. Everyone pulls their own weight.

Team Up

Now three strong we worked together and rode on through the night. About an hour later, as the eastern sky brightened so did our spirits. In 30 minutes, a beautiful sunrise greeted us and I began to entertain thoughts of finishing once again.


That’s when the next MMR hit. Backing up, earlier in the night, before the mishap in Syracuse, there was a nice lightning show down south. Not worried about having to ride through it, I didn’t think about how it was soaking the roads in our path.

It means either trying to ride the ditch or carrying. One cannot even push the bike on the road because the mud builds up and freezes the wheels. Missing my middle gears, there was no way I was going to pretend I had a mountain bike. Steve actually was riding a mountain bike and so he had some success riding to the side. Molly and I carried.

Four Miles

For four miles we carried. Built on a grid, each segment of road is exactly one mile. Each mile carried felt like an eternity. Over each hill we hoped to see a stop sign marking the end.

That is when we would stop and clean the mud off shoes, cleats, and the bikes, if we were dumb enough to try to ride any part of it. The cleanup took about 20 minutes. Walking a one mile segment at about a two mile per hour pace followed by the cleanup meant each MMR cost about 50 minutes of time.

Do you remember those old cartoons where the characters are moving but the same terrain gets recycled? That’s what this felt like. Haven’t I passed that tree before? Are We Even Moving?

After the third mile of carrying our hearts sank. Ahead was yet another MMR and another mile of carrying. Up to this point Molly had endured without complaint. Now her determination began to flag, as did mine. How much more of this can we take?

“What do you have to say about this predicament?”, she asked, somewhat rhetorically.

I repeated a line that Frank told me back at the starting line. “You have to embrace the suck”.

Satisfied with this response we accepted our fate and trudged on, not knowing this was to be the last time.


The halfway point was Beatrice (150 miles). I was supposed to be here by 6:00 am and it was now almost lunchtime. This is where Steve tossed in the towel and called someone to pick him up. I couldn’t blame him.

“Do you need a ride to Lincoln?”, he asked me. I politely declined but congratulated him on sticking it out thus far thanked him for being a good guy.

This was probably my lowest point, other than the truckstop. I was very hungry but the store’s fresh food options were dismal. I gambled on a sausage and egg biscuit, but it didn’t pan out. Tossed into the garbage after one bite. I settled on a giant payday candy bar and a coke but my stomach wasn’t happy and tossed them also.

“I’m not stopping”, I told Molly somewhat defiantly, popping another bread ball into my mouth. It was seasoned with some good ole Nebraska dirt, from the MMR’s. (Note to self: make sure you seal those ziplog bags containing foodstuff) She was inside the store talking to her husband on the phone.

“Me neither!”, she exclaimed.

And then there were two

Leaving Beatrice we turned north headed back to Lincoln. For the first time since the starting line, we’re now getting closer to the finish instead of further.

We were wearing down and saddle sore but worked together and did alright despite now headed into a stiff headwind. As expected, our pace slowed considerably. I was missing those middle gears more than ever as they are most needed when riding into the wind, over rolling hills.

After the MMR’s any chance we had of finishing on time was over. If I had had a working derailleur I might have tried anyway. It would have meant crossing the finish line at say 2:00 am Sunday morning. Another night of riding. The last 50 miles being the hilliest of the course, I knew it would be a struggle, literally uphill.

Without saying anything to Molly, who was still talking about finishing, I began to calculate where to pull out. 200 miles sounded like a good number. That’s the number of miles I should have rode at Unbound back in June. It felt a bit like a consolation prize, but I was ok with it.


Rolled into the Casey’s General Store in Wilbur (mile 176) at 1:30 pm. Here was a first class watering hole, complete with fresh pizza and icey’s. I hadn’t eaten solid food in almost 24 hours.

We got some looks from the nice townsfolk of Wilbur and we must’ve smelled bad. They were polite about it, but kept a respectful distance. Not that I could blame them. I doubt it helped matters that one of the items on my shopping list was a bar of soap, but we sure thought it funny.

“Try to look serious”, she told me before taking this shot.

What do you buy when strung out from the road? Soap and iceys, of course.

This is when I told Molly about my plan for stopping at 200. By this time she was getting tired, suffering from saddle sores and readily agreed. Our next stop was Crete at mile 190. The next one after that, mile 225.

We decided Crete was the place and called our respective rides so they could meet us there.

Molly at mile 176

The End

It was anti-climatic pulling out at 190. Definitely felt like there should have been more to this story. I had another 100 miles left in the tank. But, was satisfied with getting this far, after the earlier mishap. It could have been worse. This is why we never take a finish for granted. Shit happens. It’s all about the execution. The course has the final say. Find something to like about it.

Molly and I said our goodbyes, exchanged contact info and called it a day. A Very Long Day.


Getting back to Lincoln, had a nice beer and burger and soaked in the atmosphere of Gravel Worlds’ finish line. This Is A Great Event. Its gotten bigger over the years but has retained an Indie vibe. The organizers are very nice and cool people. I’m very glad to see their success.

Went back to the hotel around 7:00 pm, showered (of course) and slept for 12 hours. Woke a little sore and very hungry. I had the first of two breakfasts, followed by a couple of lunches. Later, I met my sister in KC and we enjoyed a nice dinner.

All-in-all a pretty good ride.

Next Time

Will I do it again, who the hell knows?

First 190 miles of a 302 mile course around Lincoln, NE

Top 10 Reasons Cyclists Choose Not to Hate the Warm Weather

With summer coming you’d think it’d be a cause to gripe but this post is trying to find something to like about it.

10. Plenty of daylight means we get to ride any damn time we please.

9. Being outside exerting ourselves and we get used to the heat, unlike others who’re afraid to leave their cars to walk across a parking lot.

8. Those frozen water bottles thaw out about when you really need a cold swig.

7. Getting nice and sweaty before public interactions ensures proper social distancing rules will be followed.

6. No need for extra layers. Put on shorts, jersey and we’re good to go.

5. Beers taste unbelievable after a long day sweating it out.

4. Food trucks are easy to find.

3. Events every weekend provide a convenient excuse to get out of yard work or anything for that matter.

2. No problem finding that seat on the patio of your favorite bistro and who wants to eat inside anyway?

  1. When else would you get a chance to chug pickle juice?

2020 Year in Review

I think we can all agree that 2020 was pretty rough. Many lost their jobs and loved ones. Our economy tanked. Businesses failed. Governments teetered on the brink. It felt like 1918 and 1930 combined.

An absolutely terrible year and it ain’t over yet. For all but a few of us, the worst in memory. So please forgive dear reader, this painful look into a past yet unhealed.

There were other declines to reckon with. In nearly every personal pursuit, 2020 pretty much sucked.

Mine’s cycling. So, how’d that work out? Not great. Most events, and all of the big ones were canceled. Dirty Kanza (now Unbound Gravel) was first postponed, then cancelled. The goblet would have to wait (was to be the 5th). Gravel Worlds went virtual. It was both disappointing and a relief. The right decision. But, it left a void in training resolve. Why suffer through all those miles now? What’s the point?

Paradoxically, cycling as a hobby enjoyed unprecedented success. People started riding their bikes. The benefits were immediate and obvious. Parents now spending quality time with their kids, instead of following their typically obsessive and harried schedules. Senior citizens and others (who look like they could use a little exercise) were now on the trail. Not just the typical hard core athletes. I welcomed them and offered encouragement. The trail is for everyone. The more the merrier.

A perfect pandemic activity. Tailor made for lockdown conditions. We can still ride while maintaining a safe distance. We can meet fitness goals (when so many others have gone awry) and blow off steam. It’s fun, cheap and anyone can do it.

Another silver lining, the pandemic induced conditions, i.e. isolation, schedule interruptions and travel restrictions opened up lots of free time. It offered the opportunity to work on weak areas of my game. Now that all rides are non-stop and solo, I can become adept at self-reliance. I learned how to carry more water, worked on electrolyte and caloric replenishment strategies. These are critical aspects in endurance cycling and areas I needed to improve.

As the year drew to a close a personal best in yearly total mileage was reached. A typical year is around 8K mi (12.8K). I’ve toyed with the 10K mi (16K km) mark for years, but due to injuries and travel was never able to get there. The yearly total reflects a commitment to a healthful lifestyle. It requires a focus on recovery and ancillary goals (rest, diet, etc.). It means being on track to ride well into the future, to enjoy its benefits for as long as possible.

Why I ride. I passed that previous yearly total by a fairly wide margin. But, exactly how far, or how fast, isn’t the point. It’s that we never stop.

Top 10 Reasons Cyclists Choose Not to Hate the Cold Weather

With winter coming you’d think it’d be a cause to gripe but this post is trying to find something to like about it.

10. Bubba’s are in the deer woods instead of rolling coal.


9. Don’t need to carry very much water.

self explanatory

8. No bugs to speak of.

Nuff said although some are actually quite tasty.

7. Roadkill stays fresh much longer.

Who hasn’t caught a good whiff of that varmit on the side of the road that’s well past its shelf life?

6. Can finally start carrying snickers bars again.

A fav in my saddlebag.

5. Brewpubs now have room on their patios.

Sure, it might be a tad nippy but that IPA can warm you right the fuck back up.

4. Sweat actually works as intended.

Really fun on the hills, wet up, dry down.

3. The noobs have all left the trail.

Not to be mean, the trail’s for everyone. Still, not going to miss those that don’t follow its etiquette.

2. No more salt dripping into the eyes or encrusted into our gear.

No, those are not salt stains on my shorts.

1. Snotrockets for the win.

We don’t need no stinking sinus infections.

“Nice Spandex”

The driver overshot the white line that marks where the crosswalk begins by about one-and-a-half car lengths.

I was cursing under my breath as I navigated around his car, placing me into the onrushing traffic.

He must have heard as he shouted at me after I passed. Keep riding I told myself, but against my better judgement, circled back and issued a fairly standard reply:

“WHAT?!!!!”, I shouted back.

It’s a busy intersection servicing an even busier interstate interchange. There must be 10,000 cars passing through daily. I’ve passed through myself on a bike countless times and have long since ceased being surprised by what happens here.

It’s an important transition point between riders who stay local and those who want to continue in the greater metro area. To say it’s not built for cyclists is an understatement, but this is the only way out of town.

“Nice Spandex bleep bleep bleep”, was his reply.

“Fuck-off”, I told him nonchalantly and turned back onto the original pathway.

I thought it was over, but this is when his engine roared to life and with tires squealing, he made a right-turn from the left-turn lane, cutting off the other drivers who were in the right-turn lane. He next made another right-turn, hopped the curb, crossed my path and forced me to brake hard to avoid a collision. Clearly this cat’s off his MEDs.

I quickly went around his car yet again, back onto the path and made a beeline for the nearby Circle-K service station, where I knew there’d be witnesses in case the situation escalated further.

Apparently he wasn’t interested in having witnesses and continued on shouting epithets and speeded away.

I was mildly shaken, but continued on with my ride.

On a scale of 1 to 10 this was about a 5. I’ve had much worse. From a danger perspective, it was fairly low. More of an irritation.

I’m not unique, ride enough miles and this kind of event becomes fairly commonplace.

I’ve given up trying to figure out the why. There’s no pay dirt in it. It’s more about trying to make sure it doesn’t bring me down, discourage from engaging in an activity that I have every right to be doing.

A little while later, on the trail, still a bit down, when I passed by a young mother walking. I slowed down and overheard her telling others that her daughter was on a bike but the two separated. I remembered seeing the little girl, stopped, assured the mom that it was going to be OK, that I’d seen her a hundred meters away, and would help them get reunited.

It felt pretty good to help and erased the negativity of earlier. It also helped seeing the other people rallying around the young mother and her lost daughter.

These types of occurrences are not unusual on the trail. Once, I delivered a juice-box to a kid going into diabetic shock on the Big Dam Bridge. His frantic mother had just retrieved it from her car in the parking lot but was maybe a mile from her child. It was one of the best miles that I’ve ever ridden. Another time, an old man who happened to be a veteran, got his electric wheelchair stuck off the path, and couldn’t get back onto it. Helping others in these types of situations is a privilege. We get more from it than they do.

A good metaphor for life. Ignore the bad stuff (that can’t be fixed), embrace the good. Do what you can to help others.

And ride on.

Remembering Mom

My earliest memories of Mom were framed by the ’60’s.  I’m not talking about the late 60’s, Vietnam, Nixon, Hippies, but the earlier post-war boom, rise of suburbia, shopping, passenger trains, cool cars, Beatles, Beach Boys, NASA, Kennedy’s, when everything seemed shiny, new and above all with promise.

She thrived in that era but didn’t choose sides.  Not too conservative, nor too progressive, straddling the line, taking the good from each.  Later, when the Hippies came into fashion, she borrowed stuff that she liked.  Peace symbols, make love not war, happy faces, bell-bottom jeans, sandals (not the casual sex and drugs part).  Again, the good stuff.

As the 60’s turned into the 70’s things changed.  Some of that promise turned hard.  Wars, political strife, etc, started to bring us down.  Along with that Mom and Dad persevered, and tried to make the best of it, for all six of their children.

Some of those early memories, bringing home lizards, snakes, sometimes alive, sometimes dead. She didn’t much care for either.  Those early days, with so many babies in the house, she was all business.  I loved her, of course, but also sometimes feared her. I feared crossing paths either when in the wrong, or when she had a vacuum cleaner in hand.

Boy did she clean.  The house made spotless on a daily basis.  I didn’t appreciate how much work that was until later, after realizing I would never live up to her exacting standards in that regard.

Her care for us was near perfect.  Every day before being sent off to school was a careful inspection.  We were expected to have combed hair, brushed teeth, serviceable clothes, ample supplies in hand.  Getting out that door was a business transaction and non-negotiable.  That continued all the way until high school graduation.  My last year, she literally dragged me out of bed on a daily basis.  Would douse me with cold water if necessary.  I Was Going To School. (Although I might not stay there).  If there was a big ballgame, concert, play, recital, any kind of award, you can bet she’d make it.  Same goes whenever trouble came.  Trips to the principal’s office, tickets, citations, summons, tardies, unauthorized absences, always routed through her desk first.

In dealing with sickness or injury, it was under control.  So many disasters, one of my siblings has made a career in the emergency management field, has literally written a book on the topic.  With six active, willful, rambunctious kids, things sometimes went haywire.  All the trips to the emergency room, with broken bones, teeth, dislocations, sprains, stitches, gashes, punctures, bites, concussions, black eyes and contusions.  Trips to the fire station for help getting a finger, hand or foot dislodged and/or unstuck from a gate, pipe, railing or nut.  There was jaundice, appendicitis, meningitis, flu, fevers, infections of endless varieties.  Fist-fights, injuries on the playing field, and various corrective surgeries.  Once even alcohol poisoning.  That was her job.  Dad only brought in when critical which thankfully was nearly never.  She would have made a damn good doctor.  Calm, collected, thorough, decisive.  Could administer a cold compress (to suppress bleeding) with one hand, a baby in the other, all the while calmly conferring with a doctor on the phone.

She was attentive.  When in conversation, it was about us.  Never about her. Those stories we told her never got turned in her direction.  She was happy to discuss it as thoroughly as we pleased.  Never admonishing us for blabbing on or to get to the point.  Even when at our worst, she always thought the best, and because of that, eventually, we were able to live up to those expectations.

She was that way with everyone.  With Dad, she would happily watch him carry the room.  That she did for most of her life.  She stood in the background. An elegant presence.

I can remember one day, must have been 2nd or 3rd grade.  She came to my classroom to bring cookies (or something).  It was a HUGE deal and I was bursting with pride.  The other boys, catcalled and hooted (which she ignored).  Probably had on some kind of groovy dress, with stylish boots, hair was always perfectly done.  This in Perry, Kansas, a town of 499 (491 after we moved away).  A bit of Hollywood glamour in the middle of the cow pasture.

She excelled at everything and worked (out of the house) when we got older.  One of her big questions, what if she hadn’t got married at a young age, continued past college into the workforce?  My answer, she would have had a sensational professional career, if only born twenty years later.

As it was she flourished in things there was time for.  Art was a particular strength, progressing to the point where she ran the art program for a local retirement community.

I was always proud of her, but I feared her judgement.  In my teens, as I went through a rebellious phase, she approved of just a few friends.  Those she did, I found out later were gold.  Those she didn’t, not so much.

She did not suffer fools, everyone knew where they stood with her.

She and Tim came to our wedding.  Just those two.  It didn’t matter, having her (with Tim) was good enough for Cindy and me.  Her endorsement rang clearer than a wedding hall of thousands.

And then when the babies started coming, she was there.  Grandma on the train, my kids called her.  In those early days, before Dad and she remarried, she’d come by Amtrak.  The kids adored her.  She was fabulous with them and we had such good fun.

Later, with Dad, it was more of the same.  Always about us, never them. They brought strange and wonderful things.  Once, a hamster, Goldenberg he was called.  Fully outfitted with the hamster trails and what not.

But there was more.  Bikes, toy trucks, dolls, puzzles, legos, books, clothes, and lots of love.  We’d eat out, go to the park, zoo, hike, bike, bowl, swim, dig, dive, drink.  Didn’t much matter where as long as we were together, it was all good.

In many of her last years was a dysfunction that slowly robbed her vitality.  A GI tract ruined in a botched procedure, by an incompetent surgeon.  Most of us (in the first world) eat too much and she could hardly at all.

Near the end, as her body wasted away, she soldiered on.  Weight down to just 70 pounds and still a brave and dignified face.  Making the most of what remained.

I feel cheated.  We should’ve had another ten years.  She held up her end of the bargain.  The graduations, weddings, great-grandchildren that will never know.

But, the time we had was more than we could have asked for.

Designing an Authorization System: a Dialogue in Five Scenes

This posting’s setting is a blatant ripoff of perhaps the best technology overview document ever written (on Kerberos):

Designing an Authentication System: a Dialogue in Four Scenes


This dialogue provides a fictitious account of the design of an open-source authorization system called “Haros”. As the dialogue progresses, the characters Athena and Euripides discover the problems inherent in applications using common authorization systems.

When they finish designing the system, Athena changes the system’s name to “Apache Fortress“, the name, coincidentally enough, of the authorization system that was designed and implemented at Apache’s “Directory Project“.


  • Dramatis Personae
  • Scene I
  • Scene II
  • Scene III
  • Scene IV
  • Scene V

Dramatis Personae

Athena a newly promoted director of IT security and a people person.
Euripides a longtime programmer specializing in security and reigning curmudgeon.

Scene I

A cubicle area. Euripides is working on a project rollout, for a new financial system.  Athena’s walking the floor with several other executives.  She finds Euripides in the farthest corner, away from the elevator.  All of the windows are covered and the lighting is muted.

Euripides: [clearing an old pizza box from the stained guest chair] Hey stranger!  Haven’t seen you in a while.  How’s life as a corporate bigwig?

Athena’s in distress but trying to conceal it.  Before the promotion, she and Euripides worked on several projects together, the most successful, a Kerberos authentication system.  Despite his gruff exterior, she’s learned to trust his candid viewpoint, particularly on security.

Athena:    [gingerly sitting down] Not so great Rip.  Our common security authorization system totally sucks.  It’s tightly bound to the application data model and can’t be reused. It’s impossible to separate the security policy data from the business data.  We’re going to have to build yet another authorization system for this new banking project you’re working on.

Euripides: [munching on a donut] Why are you telling me?  I’m just a programmer.

Athena:    [rolling her eyes] If only there was a way to externalize security policy so that it doesn’t taint the business model. That way we could have a common fine-grained authorization system that works across every application, on every system.

Euripides: [licking his fingers] We’ve been asking for one of those for as long as I’ve been here.  It’ll happen when Hades freezes over.  Here, have a donut, you’ll feel better.

Athena:     [cringing] No thanks.  I think it’s time to ask the Gods.  Maybe, this has already been solved and we can save my team the odyssey of creating a new one.

Euripides: [eating another donut] Good luck [muttering under his breath] you’re going to need it.

Athena:     What’s that?

Euripides: Oh uh yeah, tell ’em we need better authorization tools down here.

Athena:     [walking briskly away] You better believe it.

Scene II

Euripides’ cubicle, the next morning where he periodically spaces out while reading email.  Every so often, he’ll respond with a cryptic and/or sarcastic one-liner. A strong proponent of a style of discourse known as ‘cartoon-speak’, points are added for comedic effect.  Athena knocks on the cube wall startlingly him into the present.

Athena:     [excitedly] I found the answer to our entrenched authorization problem!

Euripides: [yawning and scratching] Isn’t that wonderful.  [feigning interest] That sure didn’t take very long.

Euripides moves a brown paper bag that’s oozing some kind of liquid from the guest chair to the floor and motions for her to have a seat.  She pretends not to notice the bag has something that looks like feathers sticking out of its top and that there’s a funny smell in the air.  Is there something still moving around in it?  She can’t be sure.

Athena:    [with a crinkled nose, electing to stand] As it turns out this problem has been studied for a very long time, like for ages.  Almost as long as you’ve been a programmer, not quite.

Euripides: [perking up slightly] Is that so?

Athena:    Right, there’s a research deity called NIST and they have many priests who sit in an ivory tower handing down directives for those of us living in the ‘real world’.

Euripides: I hate it when that happens.

Athena:    I know right?  So, the model I found is called Role-Based Access Control, and it’s governed by a specification from another powerful deity, ANSI, called INCITS 359.

Euripides: [sarcastically] That’s a real catchy name.

Athena:    We’ll just call it RBAC for short.

Euripides: RBAC, isn’t that what our Linux systems have… with those Group thingies?  We have to add ourselves to them, for root and what not.

Athena:    Not exactly.  There’s a bit more to it than that.

Euripides: Like what?

Athena:     There are Users of course.  And Groups, but they don’t call them that, rather they’re called Roles.

Euripides: Like for dinner?

Athena:     Very funny.  Roles are how Users are assigned to Permissions.  Permissions are a combination of Resources and Operations.

Euripides: Sounds simple enough.  Is that it?

Athena:     Not quite.  There’s also an entity called a Session.  That’s where Roles go after the User logs in.  One or more of their assigned Roles are then activated into the Session.

Euripides: [smirking] Back to the rolls only they’re not done, so we have to put them in the oven?  Seems like a waste of time.  Why not just use the list of what’s been assigned?

Athena:     [with patience] This is keeping with the principle of least privilege.  The User is given the minimum authority to complete her meal, err tasks.  Think about when someone goes on vacation or perhaps on a maternity leave.  Do they need to be active in the system then?

Euripides: No, I suppose not.  [hopefully] Is that it?

Athena:    There’s more to it.  What we’ve described so far is known as RBAC0.  The absolute minimum that an application must do in order to be compliant.  Many times that’s all that’s needed.

Euripides: [sighing] What else is there?

Athena:    Well I’m still digging, let’s talk later.

Euripides: [relieved] Sounds good.

Scene III

The next morning, Athena catches Euripides at the Starbucks kiosk inside their business plaza. He’s waiting on coffee, listening to Spotify and pretends not to see her.  She taps him on the shoulder, forcing him to acknowledge her.

The two then grab their coffees, head to the condiment bar pouring in lots of creamer to mask the bitterness, before tucking themselves into a nearby booth.

Euripides: [audibly slurping] Well that didn’t take very long.

Athena:    [wincing] Got it all figured out.  Do you want to hear the rest of the story?

Euripides: Do I have a choice?

Athena:    Very funny.  Don’t make me place a hex on your dog.  Where were we?  Oh yeah, going over the various facets of the RBAC specification.

Euripides: I’m on the edge of my seat here.

Athena:    [clears throat] RBAC1 is for Hierarchical Roles.  That is we place inheritance relationships between Roles.

Euripides: Kind of like they’re in a family?

Athena:    Sort of.  Think about when it comes time to assign the Roles to Users, sometimes referred to as ‘Role engineering’.  It’s a pretty tricky task as you might imagine.  There are many levels of access.  A Role can be a kind of module, and linked to others via inheritance.  Perhaps Engineers need to also inherit all of the permissions that a normal User gets, plus everything that is normal for them.

Euripides: [caffeine kicking in] I see.  It saves the trouble of having to constantly update all of the Roles anytime the Permissions change for a particular use case.  Say we don’t want Users to be able to log into System X, we don’t have to change every Role, we only need to change the one.  The others will realize the change automatically via inheritance.  Also, the security administrator doesn’t have to understand that an Engineer is also a User.  They just assign them the one, and that includes the other.

Athena:    Very good.  You really are more than just a programmer.  But wait, there’s more.  RBAC2 is Static Separation of Duties.  This is where we establish mutual exclusion constraints between assigned Roles.

Euripides: Say what?

Athena:    It’s not all that complicated.  Basically, we can define sets of Roles and establish a cardinality between them.  That is out of this entire set, only so many can be assigned to a given User.

Euripides: Why would we do that?

Athena:     Think about conflicts of interests that arise in everyday scenarios.  For example, we don’t want the person writing checks also approving them.

Euripides: Why not?

Athena:     Well then they could write themselves checks, approve and then deposit into their bank accounts, illegally.

Euripides: That makes sense.

Athena:    There’s also RBAC3, Dynamic Separation of Duties.  It’s basically the same concept only with activated Roles not assigned.

Euripides: Oh, here we’re back to the Session right?  One can be assigned the ‘check writer’ and ‘check approver’ Roles but can never activate them together into a Session.  There’s a toxic relationship there.

Athena:    Very good.  You’re getting the hang of this Rip.

Euripides:  [brushing off the compliment] It’s pretty straightforward.  Ok, what else?

Athena:     That’s pretty much it.  Now, I go in front of the architecture review board and try to sell my idea of using RBAC authorization inside our business apps.  Hopefully we can stop building new authorization utilities every time we build a new app.

Euripides: Good luck.

Athena:    Why do you keep saying that?

Scene IV

After not hearing from Athena for a week, and no sign of her on slack, Euripides gets worried, and tracks her GPS location on Google to a courtyard inside their business campus, overlooking a large pond.  He finds her slumped over a park bench by the shoreline, in obvious despair.  A flotilla of turtles nearby, observing the scene somberly.

Euripides: Whoa!  Look alive there sailor!

The turtles scatter.

Athena:    [Lifting her head up] I was eaten alive by the board.

Euripides: How so?

Athena:    They hated my idea.  Told me they already understood RBAC, and it’s stupid.

Euripides: Why do they say that?

Athena:     They called it quaint and said it hasn’t worked in the ‘real world’ for a long time.

Euripides: Did you tell them the NIST Gods control the real world?

Athena:     [tearfully] Yes, but they didn’t believe me.  They said that fine-grained authorization is nearly impossible to externalize because it’s tightly bound to the application’s business rules.  For an RBAC system to compensate, too many Roles would be needed causing explosions, making a huge mess of our datacenter.

Euripides: What in hades are you talking about?

Athena:     I’m talking about ‘Role explosion’ and it happens any time context is introduced into an RBAC policy.

Euripides: Context… like attributes and such?

Athena:     Yes, like in our banking scenario we have an attribute associated with the location of the financial institution, or branch.  There are over 1,000 separate locations today and our business plan calls for 10X that over the next few years.  How do we specify that someone can be a Teller in one location and not in another?

Euripides: That’s easy.  Just create Roles with the location as part of the name.  Say Teller-North123 and Washer-South456.

Athena:    That’s what I told them too.  But they said the number of Roles gets multiplied by the number of locations.  So if we have two Roles: Teller and Money Washer, and 1,000 locations, we end up with over 2,000 Roles to manage!

Euripides: Ay yi yi I see the problem.

Athena:    The architects say the only way to fix it is to join the policy entities, i.e. User, Role, and Perm, with the Bank’s data, that includes its locations.  This is hopeless because every application must have its own policy engine, one that understands its particular data model.

Euripides: Sounds like we’re back to square one.  Now what?

Athena:     Well, they’re talking about this new kind of authorization system called Attribute-Based Access Control, or ABAC.  It downplays the Role.  Everything is just an attribute, that can then get linked with a User at runtime.

Euripides: I mean, isn’t that just an Access Control List?

Athena:     Well yeah, but there’s more, like dynamic policies.  In ABAC, policies are expressions in which the various linked attributes are combined with the traditional security entities like Roles and Resources.   Let’s say that I have a policy where the ‘Teller’ Role is still required to gain access to a cash drawer at a financial institution.  We can also link additional attributes, like location.  These attributes can come from anywhere.  Something from the runtime environment, like location, time, IP address, platform, temperature of processors.  Attributes also come from the the application domain.  Things like hair color, favorite type of beer, how many donuts eaten yearly, literally anything under the helios.

Euripides: [rubbing his belly] That sounds loosey-goosey to me and again we still have our security data tightly bound to the application data.

Athena:    You haven’t even heard the worst of it yet.  The most popular ABAC systems use XML to transmit the data between their intermediaries.

Euripides: [retracting in horror] That’s bloody awful.

Athena:    [despondently] If only there was a way to combine RBAC and ABAC.  We could keep our common security data model and policy engine and combine a few attributes, like location, as needed.

Euripides: Holy Toledo, is that even allowed by the NIST Gods?

Athena:    I don’t know but I’m going to find out.

Euripides: Good luck.

Athena:     Stop saying that.

Scene V

The following week at Euripides cubicle.  Athena knocks, startling Euripides from a mid-afternoon siesta.

Euripides: [groggy and regretful of a third IPA during lunch] There you are.  How’s it going today… have you found a solution to your exploding Roles?

Athena:    [grinning] I sure did, and the architecture board has approved my plan for externalizing authorization.

Euripides: Wuff.  How’d you manage to pull that off?

Athena:     It was surprisingly easy.  First, there’s nothing in RBAC that says that attributes aren’t allowed.  So from a standards perspective we’re in the clear and the NIST Gods can’t hex our offspring.

Euripides: [nervously looking at a framed portrait of a dog on the cubicle wall] Oh, yeah, that’s good.  Did the NIST high priests tell you how?

Athena:    They gave me some ideas.  There’s the user-role activation phase… back to our Banking example… remember the two Roles and 1,000 locations?

Euripides: [groaning] Like it was yesterday.

Athena:    As we learned earlier, in RBAC, assigned Roles must be activated into the Session before a particular User can perform operations on the Role’s corresponding resources.

Euripides realizing he’s famished, snatches a cookie wedged against a burger from a day-old takeout box on his desk, almost takes a bite, thinks better of it, (trying to be nice) offers it to Athena, who vigorously shakes her head and frowns.  He then shrugs and begins eating it, a bit of ketchup hanging from one side dropping onto his shirt.

Euripides: [talking with his mouth full] How could I forget?

Athena:     [disgusted] Anyway, we can add a constraint during activation to detect whether the Role being activated matches location.  For example, only activate the Teller Role for Curly when he’s at the North branch.

Euripides: [takes a swig from a two-liter of mountain dew and burps with evident gusto] ‘scuse me.  That’s the policy but how is it enforced?

Athena:     Could … you …

Euripides: Wha?

Athena:     [waving her hands] ew! Just … never mind.  We’re making the constrained Roles special to the system.  The policy engine has to know when activating any Role, that it might have a dynamic constraint placed upon it.  Here, a property associated with the Role’s name will do quite well.

[clears a tiny space on the cluttered whiteboard and begins drawing]:

Role: Teller:locale

Role: Washer:locale

Euripides: This covers how the authorization system knows when to check for a dynamic constraint, but where will the actual attribute values be stored?

Athena:    On the User’s entity of course.  With RBAC, there is already a User-Role assignment that is bound to the User entity.  We simply need to place a couple of delineated properties on that assignment. For example the Role assignment looks like this:

[draws on whiteboard]:

User: Curly

Role Assignment: Teller:locale:North123

Role Assignment: Washer:locale:South456

Euripides: We’re still missing a piece here.  How does the authorization system get the current valid values of a dynamic constraint?  For our scenario, which locale they’re in?

Athena:    It just pushes that into the runtime context…

[draws on whiteboard]:

Session session = createSession("Curly", "locale:North123");

Euripides: Ah!  Now, when the runtime activates Curly’s Roles, it knows that they’re special and will compare the value of the constraint pushed into the API with that stored on the User-Role assignment.  Here, Curly will be a Teller because we’re in the North, right?

Athena:     That’s right. There really is more to you than your curmudgeonly demeanor suggests.

Euripides: [reflectively, with a bit of ketchup still on his shirt] Yep.  Sometime’s it’s hard for me to be humble.  What’d the board have to say?

Athena:    [handing him a napkin] What could they?  We’re pushing into the financial system as we speak.  The Bank is happy because now we’re not spending a bunch of money on a new ABAC system.  We just made a couple tweaks to our old RBAC system and everyone’s happy.

Euripides: The Gods must be pleased, maybe we’ll finally get raises.

Athena:    [sarcastically] Good luck.